博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES入门(二)Elasticsearch之Query DSL:ES增删查改、聚合分析
阅读量:4299 次
发布时间:2019-05-27

本文共 8258 字,大约阅读时间需要 27 分钟。

ES入门(二)Elasticsearch之Query DSL:ES增删查改、聚合分析

面向文档的搜索分析引擎 vs 面向对象的应用系统


 elasticsearch是面向文档的搜索分析引擎。

  • 应用系统的数据结构都是面向对象的,复杂的
  • 对象数据存储到数据库库,只能拆解开来,变为扁平的多张表,每次查询的时候还得还原对象格式,相当麻烦
  • ES是面向文档的,文档中存储的数据结构,与面向对象的数据结构是一样的,基于这种文档数据结构,es可以提供复杂的索引、全文检索、分析聚合等功能
  • es的document用json数据格式来表达

简单的Query DSL


(1)快速检查集群的健康状态


GET /_cat/health?v

(2)快速查看集群中有哪些索引


GET /_cat/indices?v

(3)创建索引与删除索引


PUT /my_index001?pretty     创建索引DELETE /my_index001?pretty  删除索引

(4)商品的crud

  方法一:插入数据,自动生成document的 _id


POST /my_index001/_doc{  "name":"奶粉",  "dec":"婴幼儿奶粉",  "price":270,  "producer":"奶粉producer",  "tags":["婴幼儿","二段"]}

  方法二:插入数据,手动指定document的 _id


PUT /my_index001/_doc/1{  "name":"奶粉",  "dec":"中老年奶粉",  "price":250,  "producer":"中老年奶粉producer",  "tags":["中老年","补钙"]}

  查询所有document


查询索引my_index001下的所有数据GET my_index001/_search{  "query": {    "match_all": {}  }}返回结果{  "took" : 1,  "timed_out" : false,  "_shards" : {    "total" : 1,    "successful" : 1,    "skipped" : 0,    "failed" : 0  },  "hits" : {    "total" : 2,    "max_score" : 1.0,    "hits" : [      {        "_index" : "my_index001",        "_type" : "_doc",        "_id" : "fXbW9nQBgKKpTl0QYML0",        "_score" : 1.0,        "_source" : {          "name" : "奶粉",          "dec" : "婴幼儿奶粉",          "price" : 270,          "producer" : "奶粉producer",          "tags" : [            "婴幼儿",            "二段"          ]        }      },      {        "_index" : "my_index001",        "_type" : "_doc",        "_id" : "1",        "_score" : 1.0,        "_source" : {          "name" : "奶粉",          "dec" : "中老年奶粉",          "price" : 250,          "producer" : "中老年奶粉producer",          "tags" : [            "中老年",            "补钙"          ]        }      }    ]  }}

    返回结果中_id=fXbW9nQBgKKpTl0QYML0的文档是方法一没有指定ID的方式下es帮我们自动生成的document的ID;_id=1的文档是我们手动指定document的ID的情况下插入的数据,如果id已经存在则报错。

返回结果中的信息:

took:耗费来几毫秒

time_out:是否超时,这里没有
_shards:拆分成来几个分片,若有多个分片,对于搜索请求,会打到所有的primary shard(或者它的某个replica shard也可以)
hits.total:查询结果的数量,2个document
hits.max_score:score的含义就是一个document对于一个search的相关度的匹配分数,越相关,就越匹配,分数也高
hits.hits:包含了匹配搜索的document的详细数据

  修改商品:更新指定document的指定字段


POST /my_index001/_doc/1/_update{  "doc" : {      "price" : 280   }}

  替换document:此方法不是更新指定字段,而是将_id=1的document整个替换为下面插入的新的document。注意:若用这个方法更新,需要将原有的不需要更新的字段全部带上,否则会出现字段丢失。


POST /my_index001/_doc/1{  "price" : 280}

  删除数据


DELETE /my_index001/_doc/1

bool查询:Query&Filtering与多字符串多字段查询


一个bool查询是一个或者多个查询子句的组合:总共包含4种子句。其中2种会影响算分,2种不影响算分

  • must              必须匹配。贡献算分
  • should           选择性匹配。贡献算分
  • must_not       Filter Context:查询子句,必须不能匹配
  • filter               Filter Context:必须匹配,但是不贡献算分

相关性并不只是全文检索的专利。也适用于yes|no的子句,匹配的子句越多,相关性评分越高。如果多条查询子句被合并为一条复合查询语句,比如bool查询,则每个查询字句计算得出的评分会被合并到总的相关性评分中。

bool组合查询


GET /my_index001/_search{  "query": {    "bool": {      "must": [        {"match": {          "name": "奶粉"        }}      ],      "must_not": [        {"match": {          "name": "牙膏"        }}      ],      "filter": {        "range": {          "price": {            "gte": 200,            "lte": 300          }        }      },      "should": [        {"match": {          "producer": "producer"        }}      ]    }  }}

上面这个bool查询中用到must、must_not、should、filter,这四个可以并行以任意顺序出现,在比的bool查询中,没有must条件,should中必须满足一条查询。

查询语句的结构会对相关度算分产生影响


查询语句GET /my_index001/_search{  "query": {    "bool": {      "should": [        {"match": {"tags": "老人"}},        {"match": {"tags": "婴儿"}},        {"bool": {          "should": [            {"match": {              "tags": "中年"            }}          ]        }}      ]    }  }}返回结果:"hits" : {    "total" : 3,    "max_score" : 2.345461,    "hits" : [      {        "_index" : "my_index001",        "_type" : "_doc",        "_id" : "2",        "_score" : 2.345461,        "_source" : {          "name" : "奶粉",          "dec" : "老人奶粉",          "price" : 240,          "producer" : "老人奶粉producer",          "tags" : [            "老人"          ]        }      },      {        "_index" : "my_index001",        "_type" : "_doc",        "_id" : "fXbW9nQBgKKpTl0QYML0",        "_score" : 2.345461,        "_source" : {          "name" : "奶粉",          "dec" : "婴儿奶粉",          "price" : 270,          "producer" : "奶粉producer",          "tags" : [            "婴儿"          ]        }      },      {        "_index" : "my_index001",        "_type" : "_doc",        "_id" : "1",        "_score" : 1.4779618,        "_source" : {          "name" : "奶粉",          "dec" : "中年奶粉",          "price" : 240,          "producer" : "中年奶粉producer",          "tags" : [            "中年",            "帮助睡眠"          ]        }      }    ]  }

上面的查询中tags="老人"和tags="婴儿"的文档的扽都为2.345461,而tags="中年"的文档得分为1.4779618,是因为前面两个文档查询时条件在同一层级,而最后一个文档查询条件的层级则是在前两个文档的下一层,上面的查询语句可见。

控制字段的boosting,控制关键词搜索结果的得分


查询语句:GET /my_index001/_search{  "query": {    "bool": {      "should": [        {"match": {          "tags": {            "query": "老人",             "boost":4          }        }},        {"match": {          "tags": {            "query": "婴儿",            "boost":1          }        }}      ]    }  }}返回结果:"hits" : [      {        "_index" : "my_index001",        "_type" : "_doc",        "_id" : "2",        "_score" : 9.381844,        "_source" : {          "name" : "奶粉",          "dec" : "老人奶粉",          "price" : 240,          "producer" : "老人奶粉producer",          "tags" : [            "老人"          ]        }      },      {        "_index" : "my_index001",        "_type" : "_doc",        "_id" : "fXbW9nQBgKKpTl0QYML0",        "_score" : 2.345461,        "_source" : {          "name" : "奶粉",          "dec" : "婴儿奶粉",          "price" : 270,          "producer" : "奶粉producer",          "tags" : [            "婴儿"          ]        }      }    ]  }

boost设置为4的关键词的查询结果得分为9.381844,boost设置为1的关键词的查询结果得分则为2.345461。若两个boost得分都设置为4,则返回结果两个文档的得分都等于9.381844。

短语检索(phrase search)


以上的查询使用的都是全文检索,全文检索会将输入的搜索串拆解开来,去倒排索引里面去一一匹配,只要能匹配上任意一个拆解后的单词,就可以作为结果返回。相反,短语检索要求输入的搜索串必须在指定的字段文本中,完全包含一摸一样的,才可以算匹配,才能所谓结果返回。语法如下:

GET /my_index001/_search{  "query": {    "match_phrase": {      "dec": "老人奶粉"    }  }}

聚合分析


    在使用es的聚合分析功能之前必须将聚合分析的字段的fielddata属性设置为true,否则会报action_request_validation_exception这个异常,设置索引的某个字段的fielddata属性语法如下:


PUT /my_index001/_mapping/_doc{  "properties": {    "name":{      "type": "text",      "fielddata": true    }  }}

    计算每个name下的商品数量,注意若有中文需自行设置IK分词器,es内置的中文分词器会把中文拆分成一个个单独的文字:


聚合语法:GET /my_index001/_search{  "size": 0,                   //若不加size,会把聚合用到所有的document也一并返回  "aggs": {    "group_by_name": {         //聚合返回结果名称      "terms": {        "field": "name"        //聚合字段      }    }  }}返回结果:"aggregations" : {    "group_by_name" : {                        //聚合返回结果名称,与上面相对应      "doc_count_error_upper_bound" : 0,      "sum_other_doc_count" : 0,      "buckets" : [                            //聚合结果        {          "key" : "奶粉",          "doc_count" : 3        },        {          "key" : "裤子",          "doc_count" : 1        }      ]    }  }

    计算name="奶粉"下每个tag下的商品数量:


GET /my_index001/_search{  "size": 0,   "query": {    "match": {      "name": "奶粉"    }  },   "aggs": {    "group_by_tags": {      "terms": {        "field": "tags"      }    }  }}

    先分组,再计算每组的平均值,计算每个name下商品的平均值:


GET /my_index001/_search{  "size": 0,   "aggs": {    "group_by_name": {      "terms": {        "field": "name"      },      "aggs": {        "avg_price": {          "avg": {            "field": "price"          }        }      }    }  }}

    计算每个name下的price的平均值,并按照price升序排序:


GET /my_index001/_search{  "size": 0,   "aggs": {    "group_by_name": {      "terms": {        "field": "name",        "order": {          "avg_price": "asc"        }      },      "aggs": {        "avg_price": {          "avg": {            "field": "price"          }        }      }    }  }}

按照指定价格范围区间进行分组,然后在每组内再按照tag进行分组,最后计算每组平均价格:


GET /my_index001/_search{  "size": 0,   "aggs": {    "group_by_price": {      "range": {        "field": "price",        "ranges": [          {            "from": 0,            "to": 100          },          {            "from": 100,            "to": 200          },          {            "from": 200,            "to": 300          }        ]      },      "aggs": {        "group_by_name": {          "terms": {            "field": "name"          },          "aggs": {            "average_price": {              "avg": {                "field": "price"              }            }          }        }      }    }  }}

 

转载地址:http://rupws.baihongyu.com/

你可能感兴趣的文章
Pull Request流程
查看>>
Lambda 表达式
查看>>
函数式数据处理(一)--流
查看>>
java 流使用
查看>>
java 用流收集数据
查看>>
java并行流
查看>>
CompletableFuture 组合式异步编程
查看>>
mysql查询某一个字段是否包含中文字符
查看>>
Java中equals和==的区别
查看>>
JVM内存管理及GC机制
查看>>
Java:按值传递还是按引用传递详细解说
查看>>
全面理解Java内存模型
查看>>
Java中Synchronized的用法
查看>>
阻塞队列
查看>>
linux的基础知识
查看>>
接口技术原理
查看>>
五大串口的基本原理
查看>>
PCB设计技巧与注意事项
查看>>
linux进程之间通讯常用信号
查看>>
main函数带参数
查看>>