简介 在实践中最常使用的就是查询,而Elasticsearch又提供了丰富的HTTP接口供人们调用(JAVA的高级API其实也差不多),这里借用kibana提供的开发者工具,使用HTTP API对遇到过的常用查询进行总结。
数据集 我采用科大讯飞的长文本分类数据集提供测试
https://github.com/CLUEbenchmark/CLUEDatasetSearch
其为json格式的文本集,具体示例数据如下
1 2 3 4 5 { "label" : "11" , "label_des" : "薅羊毛" , "sentence" : "活动新用户领5元现金即日起成功注册酷划的新用户,填写邀请码80008即可领取5元现金奖励哦。小伙伴们不要错过,赶快来酷划锁屏领红包吧~每天解锁50次,一年可赚上千元酷划锁屏是一款可以自动赚钱的手机锁屏APP,每次解锁手机均有数额不等的现金奖励。赚到的钱可以极速提现到微信钱包、支付宝,也可以用来购买爆款商品。除手机解锁可以赚钱外,酷划还提供邀请赚、分享赚、高额赚等十余种赚钱方式,零成本可得高额回报。三年时间里,酷划已累计服务了超一亿名用户。在手赚软件中处于无可争议的领先地位。手机赚钱,用酷划锁屏就对了功能介绍手机解锁领现金每次解锁均有现金奖励锁屏精选新鲜资讯,边看边赚零花钱十种以上赚钱方式邀请赚、分享赚、试玩赚…多种赚钱方式任你选每天花上五分钟,酷划收入翻倍领邀请徒弟收入加倍邀请好友体验酷划,建立师徒关系徒弟挣钱,师傅得现金奖励提现购物任你挑选您的收入可提现,购物,话费充值微信一元提现,极速到账官网www.coohua.com微信公众号酷划在线客服邮箱help@coohua.com,每天解锁50次,一年可赚上千块,1、客户端个人中心电商相关功能下线2、锁屏改造客户端SDK" }
索引类 创建索引 调用了HTTP PUT方法创建一个索引,且创建了Mapping和设置了索引的分片和索引信息,因为我只有使用一台节点(在Elasticsearch中节点默认即是Master,Data,Coordinating节点,如果需要子开启对于的设置可以配置yml文件,开启对于的节点角色即可),其指定了一个数据主分片(number_of_shards)和0个副本分片(number_of_replicas),且在mapping对各个字段做了定义,且label_des和sentence字段指定了分词器为IK分词器(中文分词器)的两种分词策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 PUT /data_test { "settings" : { "number_of_shards" : "1", "number_of_replicas" : "0" }, "mappings" : { "properties" : { "id" : { "type" : "keyword", "ignore_above" : 100 }, "label" : { "type" : "integer" }, "label_des" : { "type" : "text", "analyzer" : "ik_smart", "fields":{ "keyword":{ "type":"keyword", "ignore_above" : 256 } } }, "sentence" : { "type" : "text", "analyzer" : "ik_max_word", "search_analyzer" : "ik_smart" } } } }
number_of_shards:分片数量
number_of_replicas:副本数量
分词查询 在优化查询的时候我们需要对我们使用的分词器的分词情况进行查看,就可以使用该API,以下时候是使用ik_smart分词器的情况下对休闲益智这个词进行查询其分词情况
1 2 3 4 5 6 GET /_analyze { "text": "休闲益智", "analyzer": "ik_smart" }
结果如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 { "tokens" : [ { "token" : "休闲", "start_offset" : 0, "end_offset" : 2, "type" : "CN_WORD", "position" : 0 }, { "token" : "益智", "start_offset" : 2, "end_offset" : 4, "type" : "CN_WORD", "position" : 1 } ] }
查询 Term查询 (对输入的词不进行分词)
注意:这边我们查询的是休闲益智,在IK分词器中这个词被分为休闲和益智两个词,所以我们这里使用label_des的子字段keyword来查询不分词的数据(该子字段的类型为keyword),如果直接对label_des字段查询则查询不出任何数据,因为根据上面我们设置的Mapping这中定义其为text,在es倒排索引中其呗分隔成休闲和益智两个词
1 2 3 4 5 6 7 8 GET /data_test2/_search { "query": { "term": { "label_des.keyword": "休闲益智" } } }
Match查询 (对输入的词进行分词查询)
1 2 3 4 5 6 7 8 9 10 GET /data_test2/_search { "query": { "match": { "label_des": "休闲益" } } }
查询结果能查询出label_des包含休闲益智的文档,因为ik分词器将其分词为休闲和益两个词,只要文档中出现其中一个倒排索引即可完成匹配
Match and 查询 上文我们进行了Match查询,match对搜索词进行分词后再查询,只要有一个词命中文档,那么就返回文档,如果要两个词都要命中才返回文档那么就要使用bool 和must包含多个match,以下只能查询出同时包含休闲和益智两个词条的文档
1 2 3 4 5 6 7 8 9 10 11 GET /data_test2/_search { "query": { "bool": { "must": [ { "match": { "label_des": "休闲" }}, { "match": { "label_des": "益智" }} ] } } }
Match phrase match phrase和term有些类似其核心在于时候分词match phrase会对输入的词进行分词,比如term中查询休闲益智,那么会执行查询文档中是否包含休闲益智这个词条,但是ik分词器中并没有这个词,只存在休闲和益智两个词条索引term无法查询出,如果使用Match phrase查询休闲益智这个词,则会将其分隔成休闲和益智两个词,再去文档中查询同时包含这两个题词条的数据,另外其还可指定slop来规定查询的这两个词之间可以间隔多少个词
1 2 3 4 5 6 7 8 9 10 11 12 GET /data_test2/_search { "query": { "match_phrase": { "sentence": { "query": "点击自动", "slop": 10 } } } }
aggs聚合 ES聚合查询分为Bucket和Metric ,Bucket类似SQL的Group By ,Metric 类似SQL 的 AVG ,MAX ,MIN函数,并且在返回的Bucket桶中可以查看到当前桶下数据的条数
以下语句类似SQL的
select label_des as group, max(label) as max_name from data_test2 group by label_des
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 GET /data_test2/_search { "aggs": { "group": { "terms": { "field": "label_des.keyword", "size": 10 }, "aggs": { "max_name": { "max": { "field": "label" } } } } } }
Pipeline aggregations 和aggs不同的是,aggs针对的是文档的聚合,而pipeline aggs针对的aggs后的数据再做一次aggs(类似对SQL的Group By语句再做一次查询)
以下查询类似sql语句
1 2 3 select max(label_num) from ( SELECT label_des , max(label) as label_num from data_test2 group by label_des ) t
具体的pipeline类型查看官方文档
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-pipeline-max-bucket-aggregation.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 GET /data_test2/_search { "query": { "term": { "label_des": { "value": "工具" } } }, "aggs": { "tool": { "terms": { "field": "label_des.keyword" }, "aggs": { "label_num": { "max": { "field": "label" } } } } , "max_label": { "max_bucket": { "buckets_path": "tool.label_num" } } } }