美文网首页
elasticsearch外用与内观(一)-常用功能与使用方法

elasticsearch外用与内观(一)-常用功能与使用方法

作者: 人家老王 | 来源:发表于2020-12-03 08:20 被阅读0次

  在实际开发过程中,如果使用sql表现出局限性,我们就要尝试使用别的技术方案来解决问题,比如elasticsearch。

  接下来我们一起看一下es的常用功能和使用方法。

首先是安装与启动

  这部分是很简单方便的,首先从官网下载es的安装包。我们这个示例使用的是6.8.8版本,

$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.8.8.tar.gz

解压之后就可以直接用命令启动了。

$ tar -xvf elasticsearch-6.8.8.tar.gz

$ ./elasticsearch-6.8.8/bin/elasticsearch &

因为es是java写的,所以在启动的时候要确保环境中安装了jdk。

启动好之后,我们可以直接请求es的restful接口,来查看es的启动状态

$ curl  http://localhost:9200

正常的返回结果:

{
  "name" : "demo-1",
  "cluster_name" : "demo",
  "cluster_uuid" : "gs1uLoXyQseqMF0DB47_Cg",
  "version" : {
    "number" : "6.8.8",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "2f4c224",
    "build_date" : "2020-03-18T23:22:18.622755Z",
    "build_snapshot" : false,
    "lucene_version" : "7.7.2",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

接下来我们创建索引

绿颜色的这几个地方,都是我们自定义的名称,可以随意修改,其他的都是系统关键字是固定的写法。

1.png
$ curl -XPUT 192.168.60.89:9602/goods/ -H "Content-Type: application/json" —header "Accept: */*" -d '{
  "mappings":{
    "list":{
      "properties" : {
         "goodsId" : {
          "type" :    "keyword",
          "index":    false
        },
          "name" : {
          "type" :    "text",
          "index":    true
        },
          "price" : {
          "type" :    "keyword",
          "index":    true
        },
          "createTime" : {
          "type" :    "keyword",
          "index":    true
        }
      }
    }
  }
}'

标注1这里写的是goods,表示创建一个叫goods的索引,

标注2这里写的是list,表示goods索引里有个索引类型叫list。

需要注意的是,从6.0以后,es的一个索引只能有一个类型,所以我们只要按这个固定的模式创建就行了。另外,最新的7.X版本,里面已经去掉索引类型了,所以如果是使用最新版的,就不要加这个索引类型list。

标注3这里表示goodsId字段的类型是keyword,是一种不需要分词的字符串类型,不分词的意思是,值插入的时候是什么样,就存成什么样。

标注4这里表示name字段的类型是text,是一种需要分词的字符串类型。需要分词的意思是,值在插入的时候,需要额外从文本中分析出一个个词条进行存储。

当然还有其他的类型,比如Integer 、boolean等等,都是不需要进行分词的。

有了索引,我们就可以往里边插数据了。

插数据

还是一样的,绿色的部分都输入我们自定义的数据,


2.png
$ curl -XPOST 192.168.60.89:9602/goods/list/10000/_create -H "Content-Type: application/json" —header "Accept: */*" -d '
{"goodsId":"10000","name":"测试苹果","price":"9999","createTime":"2020-11-11 11:11:11"}'

标注1的地方是_create关键字,表示创建一个新文档,

标注2这个地方就是文档的内容,里边的字段名称和创建索引时设置的字段名称需要保持一致。

整个命令表示往goods索引的list类型里插入一个id是10000的新文档,
插入成功会返回这样一段提示,其中successful=1表示成功。

{"_index":"goods","_type":"list","_id":"10000","_version":1,"result":"created","_shards":{"total":3,"successful":1,"failed":0},"_seq_no":1,"_primary_term":1}
修改数据

也是一样的,绿色部分是我们自定义的数据,


3.png
curl -XPOST 192.168.60.89:9602/goods/_doc/20000/_update -H "Content-Type: application/json" —header "Accept: */*" -d '
{"doc":{"goodsId":"20000","name":"测试苹果22","price":"2222","createTime":"2020-11-11 11:11:11"}}
'

标注1 2 3的这三个关键字,都是固定的写法。

这个命令表示修改goods索引里id为20000的这个文档,
修改成功返回的也是successful=1

{"_index":"goods","_type":"_doc","_id":"20000","_version":2,"result":"updated","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":1,"_primary_term":1}
批量插入或者修改数据

我们在往es里导入数据的时候,就可以用这种批量插入的方式。

4.png
curl -XPOST 192.168.60.89:9602/goods/list/_bulk?pretty -H "Content-Type: application/json" —header "Accept: */*" -d '
{"index":{"_id":"1"}}
{"goodsId":"1","name":"苹果Apple iPhone 12","price":"9999","createTime":"2020-11-11 11:11:11"}
{"index":{"_id":"2"}}
{"goodsId":"2","name":"苹果Apple iPhone 11","price":"7777","createTime":"2019-11-11 12:11:11"}
{"index":{"_id":"3"}}
{"goodsId":"3","name":"苹果烟台红富士 新鲜水果","price":"25","createTime":"2020-11-11 13:11:11"}
{"index":{"_id":"4"}}
{"goodsId":"4","name":"Apple 苹果 iPhone 11","price":"7777","createTime":"2019-11-11 14:11:11"}
{"index":{"_id":"5"}}
{"goodsId":"5","name":"新疆阿克苏苹果 超甜 12元一斤","price":"12","createTime":"2020-11-11 15:11:11"}
{"index":{"_id":"6"}}
{"goodsId":"6","name":"苹果Apple iPhone 4","price":"400","createTime":"2008-11-11 16:11:11"}
{"index":{"_id":"7"}}
{"goodsId":"7","name":"烟台红富士苹果 大果 4粒装 3斤","price":"23","createTime":"2020-11-11 17:11:11"}'

绿色的地方和之前的插入是一样的,

标注1这里从create改成_bulk关键字,

标注2这里需要给每个文档都加一个固定的index id,用于传入文档的id,

标注3是文档的内容。执行这个命令时es会判断,如果系统里没有这个文档就插入,已经有这个文档就进行更新。

删除数据

删除文档就更简单了,只要设置索引和文档id就可以删除了。

curl -XDELETE 192.168.60.89:9602/goods/_doc/10000?pretty
查找操作

接下来是我们用的最多的查找操作。

查数据有三种类型,精确查找,全文搜索,聚合查找。

首先是精确查找:

5.png
curl -XGET 192.168.60.89:9602/goods/list/_search?pretty -H "Content-Type: application/json" —header "Accept: */*" -d '
{
    "query": {
        "bool": {
            "must": [
                { "term": { "_id": "20000"}}
            ]
        }
    }
}'

绿色部分也是输入我们自定义的名称。

我们先看标注5,term关键字和sql中的等于判断一样,用于精确比较,这里就是id等于20000的意思,
标注4的must,和sql中的and一样,表示标注5这里多个条件之间的关系,标注4也可以改成must____not或者should或者should____not,大家可以根据字面意思去理解,我们这个示例中的must再结合标注5的这个条件,表示查找必须满足id=20000这个条件的数据。

另外标注1 2 3这三个也是固定的写法。

查找成功返回的结果:

6.png

我们主要关注这4点:

标注1,表示查询耗费的时间,单位是毫秒

标注2,表示这个索引有5个主分片

标注3,是对查到的每一条数据打分的分数,匹配的越精确分数就越高

标注4,这里就是文档的具体内容

我们注意到标注3的分数字段,打分是因为es对查找的文档进行了相关度分析,在这个示例中,因为我们是用id来进行精确查找的,所以是不需要进行相关度分析,这种场景下我们可以使用filter进行查找。

filter的用法和query的用法基本没有区别:


7.png

只是在标注2这里,多加了一层filter过滤。

我们看到filter的返回结果,基本上和query返回的结果是一样的:

8.png

只是现在标注1的score字段变成0,因为filter不会执行相关度分析,所以也就不会对结果打分。

另外还有一点区别是,filter还会对结果进行缓存,有了这两点区别,filter整体查询速度要比query快,但是也正是因为filter不会对结果打分,会导致filter不能对结果进行相关度排序,所以我们在实际使用时,可以根据需要进行选择。

query和filter的区别:

9.png
全文搜索

接下来是全文搜索,格式和精确查找的query用法是一样的:


10.png

只不过把标注2这里由之前的term变成match关键字。

标注1这里的from和size和sql里的limit作用一样,用来对结果进行分页。

这个示例表示搜索两条数据,并且name里同时包含苹果 和 12关键字。

返回结果的格式也是一样的,因为是全文搜索,所以会对文档进行相关度分析对结果进行打分,这里第一条是1.3分,第二条是0.8分。

11.png

我看到返回的数据里,还是有一个是手机,有一个是水果,
现在如果想把包含水果的数据给过滤掉,可以再加一个must_not的判断,把包含斤 盒 克这种水果的键字的记录给过滤掉:


12.png
curl -XGET 192.168.60.89:9602/goods/list/_search?pretty -H "Content-Type: application/json" —header "Accept: */*" -d '
{
    "from": 0,
    "size": 100,
    "query": {
        "bool": {
            "must": [
    { "match": { "name": "苹果"}},
    { "match": { "name": "12"}}
            ],
            "must_not": [
    { "match": { "name": "斤 盒 克 "}}
            ]
        }
    }
}'

这样就可以只获取到一条苹果手机的数据:


13.png
boosting搜索

现在如果用户搜的是“苹果 4”,我们认为用户搜手机和搜水果的可能性都存在,这时我们可以使用boosting查询来对结果进行权重设置。

boosting的格式我们可以拿前边的全文搜索的格式做为一个参照。

14.png

首先我们看标注2,从原来的bool关键字改成boosting关键字

标注3从原来的must变成positive关键字,表示正向的条件,作用和must是一样的,就是必须满足positive里的条件

标注4从原来的must__not变成negative关键字,表示负向的条件

整个命令的意思是,搜索的结果必须满足positive里的条件,同时,如果和negative里的条件也匹配了,那么这个文档的得分就要打折,打折比例通过标注5这里的negative_boost参数来设置的,0.2表示打两折,最后,返回的文档得分不低于标注1这里min_score设置的分数。

我们看到返回的结果里,有苹果4手机和也有4粒包装的水果,并且是按照各自的权重比例打分的,而且返回来的都是得分大于0.15的文档。

15.png
聚合查找

聚合查找的用法也很简单,一般是这样使用的:


16.png

我们看下边标注1这里,使用price字段进行聚合,也就是group by price字段

标注2是给聚合返回的结果起的名字

标注3表示只对名称包含苹果关键字的文档进行聚合

这是返回的结果:

17.png

标注1是我们给聚合返回起的名字,标注2和标注3这里是返回的结果,就是价格是12的有1条记录,价格是2222的有5条记录。

Next:elasticsearch外用与内观(二)-当插入文档时,elasticsearch都在做什么

相关文章

网友评论

      本文标题:elasticsearch外用与内观(一)-常用功能与使用方法

      本文链接:https://www.haomeiwen.com/subject/ljgpwktx.html