前言
本文档主要简单记录一下在ElasticSearch中的一些搜索语句(基于阿里云ElasticSearch环境)。
轻量搜索
最简单的搜索应该就是一个简单的get了,如下使用get来获取数据:
GET /index_name/_search
返回结果:
{ "took" : 1, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 20, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "index_name", "_type" : "_doc", "_id" : "11", "_score" : 1.0, "_source" : { "tags" : [ "gamegroup" ], "update_time" : 1607156354, "@timestamp" : "2021-02-18T03:40:01.235Z", "id" : 11, "name" : "对马岛之魂", "status" : 0, "create_time" : 1603073095, "@version" : "1", } }, ··· ] } }
可以看到我们从index_name中获取了10条数据(默认返回10条),返回的结果在数组hits中。需要注意的是,返回结果不仅仅是告知匹配到了哪一些文档,还包含了文档本身的所有数据。
同时,针对简单匹配的搜索,我们也可以直接使用轻量搜索,在请求路径中使用_search端点,并将查询条件赋值给参数q。如下:
GET /index_name/_search?q=name:马岛
返回结果:
{ "took" : 1, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 5.1153607, "hits" : [ { "_index" : "index_name", "_type" : "_doc", "_id" : "11", "_score" : 5.1153607, "_source" : { "update_time" : 1607156354, "@timestamp" : "2021-02-18T03:40:01.235Z", "id" : 11, "name" : "对马岛之魂", "status": 0, "create_time" : 1603073095, "@version" : "1", } } ] } }
查询表达式搜索
按上面的查询我们可以实现最简单的搜索方式,但是在实际应用中存在很大的局限性,因为搜索业务的复杂性往往不会如此简单。所有ElasticSearch提供了一个丰富灵活的查询语句叫做查询表达式,它支持更加复杂的查询。 比如:
GET /index_name/_search { "query": { "match": { "name": "活动" } }, "sort": [ { "id": { "order": "desc" } } ], "from": 0, "size": 10 }
上面的查询方式主要实现的是,查询name能与活动相匹配的数据,偏移量为0,获取10条数据,同时按照id进行排序(在没有指定排序方式的情况下,默认按照匹配分数_source排序)。
复杂查询
下面进行一些相比刚才要更为复杂的查询,查询index_name下的数据,要求name可以匹配关键字“马岛”,同时需要rank_num的值大于5。
GET /index_name/_search { "query" : { "bool": { "must": { "match" : { "name" : "马岛" } }, "filter": { "range" : { "rank_num" : { "gt" : 5 } } } } } }
短语匹配
这里简单介绍一下match与match_phrase,match匹配会将关键词进行拆分品牌,而match_phrase不会将关键词拆分。所以如果需要匹配短语的话,使用match_phrase替代match即可。
1 GET /index_name/_search 2 { 3 "query" : { 4 "bool": { 5 "must": { 6 "match_phrase" : { 7 "name" : "马岛" 8 } 9 }, 10 "filter": { 11 "range" : { 12 "rank_num" : { "gt" : 5 } 13 } 14 } 15 } 16 } 17 }
高亮搜索(实践于官方文档有异,待确定)
许多应用都倾向于在每个搜索结果中 高亮 部分文本片段,以便让用户知道为何该文档符合查询条件。在 Elasticsearch 中检索出高亮片段也很容易。在前面的查询中添加一个highlight字段即可。
简单分析
Elasticsearch 有一个功能叫聚合(aggregations),允许我们基于数据生成一些精细的分析结果。聚合与 SQL 中的 GROUP BY 类似但更强大。 如下(按照parent_id字段进行聚合):
1 GET /index_name/_search 2 { 3 "aggs": { 4 "all_interests": { 5 "terms": { "field": "parent_id" } 6 } 7 } 8 }
返回结果:
1 { 2 ... 3 "hits": { ... }, 4 "aggregations": { 5 "all_interests": { 6 "buckets": [ 7 { 8 "key" : 0, 9 "doc_count" : 66422 10 }, 11 { 12 "key" : -1, 13 "doc_count" : 4716 14 }, 15 { 16 "key" : 27490, 17 "doc_count" : 1684 18 }, 19 ... 20 ] 21 } 22 } 23 }
可以看到表中,parent_id字段每一种数据占的数量多少。 同时我们可以在查询时添加一下搜索语句:
GET /index_name/_search { "query": { "match": { "platform": "pc" } }, "aggs": { "all_interests": { "terms": { "field": "parent_id" } } } }
返回结果:
1 { 2 ... 3 "hits": { ... }, 4 "aggregations": { 5 "all_interests": { 6 "buckets": [ 7 { 8 "key" : 0, 9 "doc_count" : 52428 10 }, 11 { 12 "key" : -1, 13 "doc_count" : 3494 14 }, 15 { 16 "key" : 27490, 17 "doc_count" : 1684 18 }, 19 ... 20 ] 21 } 22 } 23 }
分级汇总
查询方式:
1 GET /megacorp/employee/_search 2 { 3 "aggs" : { 4 "all_interests" : { 5 "terms" : { "field" : "interests" }, 6 "aggs" : { 7 "avg_age" : { 8 "avg" : { "field" : "age" } 9 } 10 } 11 } 12 } 13 }
返回结果:
... "all_interests": { "buckets": [ { "key": "music", "doc_count": 2, "avg_age": { "value": 28.5 } }, { "key": "forestry", "doc_count": 1, "avg_age": { "value": 35 } }, { "key": "sports", "doc_count": 1, "avg_age": { "value": 25 } } ] }
返回结果也是很好理解的,如最后一条数据表示sports的数量为1,平均年龄为25。