如何在Elasticsearch Bool查询中为不同参数配置聚合与排序
Elasticsearch 聚合排序需求实现
文档结构
{ "_index" : "admin", "_type" : "_doc", "_id" : "9rEy94EB7k-V-3UYmchn", "_source" : { "entity_title" : "Title CPP", "entity_type" : "type1", "entity_score" : 185346, "entity" : { "customer_id" : "cid1", "customer_name" : "cname1" } } } { "_index" : "admin", "_type" : "_doc", "_id" : "9rEy94EB7k-V-3UYmchn", "_source" : { "entity_title" : "Title APP", "entity_type" : "type1", "entity_score" : 12, "entity" : { "customer_id" : "cid2", "customer_name" : "cname2" } } }
当前查询语句
(注:原语句存在语法错误,已修正多余逗号)
GET /admin/_search { "size": 0, "query" : { "bool" : { "should" : [ { "query_string" : {"default_field" : "entity_title", "query" : "app*"} }, { "fuzzy": {"entity_title": {"value": "app"}} } ] } }, "aggs": { "by_entity_type": { "terms":{ "field":"entity_type", "size": 4 }, "aggs": { "by_top_score":{"top_hits":{"size":10, "sort": {"entity_score": {"order" : "desc", "mode" : "avg"}}}} } } } }
需求说明
- 按
entity_type对所有搜索结果进行聚合; query_string匹配到的结果按_score排序;fuzzy搜索得到的结果按entity_score排序。
方案一:分开聚合(独立处理两种匹配结果)
通过filters聚合将query_string和fuzzy匹配的结果分开,各自按entity_type聚合后执行对应排序逻辑:
GET /admin/_search { "size": 0, "query": { "bool": { "should": [ { "query_string": {"default_field": "entity_title", "query": "app*"} }, { "fuzzy": {"entity_title": {"value": "app"}} } ] } }, "aggs": { "matched_results": { "filters": { "filters": { "query_string_matches": { "query_string": {"default_field": "entity_title", "query": "app*"} }, "fuzzy_matches": { "fuzzy": {"entity_title": {"value": "app"}} } } }, "aggs": { "by_entity_type": { "terms": { "field": "entity_type", "size": 4 }, "aggs": { "top_query_string_hits": { "top_hits": { "size": 10, "sort": [{"_score": {"order": "desc"}}] } }, "top_fuzzy_hits": { "top_hits": { "size": 10, "sort": [{"entity_score": {"order": "desc", "mode": "avg"}}] } } } } } } } }
说明:
- 外层
filters聚合区分两种匹配类型的结果; - 内层
by_entity_type按类型聚合; - 分别用
top_query_string_hits和top_fuzzy_hits两个top_hits聚合,各自按_score和entity_score排序。
方案二:同聚合内区分结果并排序
在同一entity_type聚合下,通过两个独立的top_hits聚合,分别过滤对应匹配结果并执行排序:
GET /admin/_search { "size": 0, "query": { "bool": { "should": [ { "query_string": {"default_field": "entity_title", "query": "app*"} }, { "fuzzy": {"entity_title": {"value": "app"}} } ] } }, "aggs": { "by_entity_type": { "terms": { "field": "entity_type", "size": 4 }, "aggs": { "query_string_top_hits": { "top_hits": { "size": 10, "sort": [{"_score": {"order": "desc"}}], "query": { "query_string": {"default_field": "entity_title", "query": "app*"} } } }, "fuzzy_top_hits": { "top_hits": { "size": 10, "sort": [{"entity_score": {"order": "desc", "mode": "avg"}}], "query": { "fuzzy": {"entity_title": {"value": "app"}} } } } } } } }
说明:
- 先按
entity_type做顶层聚合; - 每个类型桶内,分别用带过滤条件的
top_hits聚合,获取对应匹配结果并按要求排序; - 此方案无需外层区分匹配类型,直接在类型桶内拆分结果。
内容的提问来源于stack exchange,提问作者Mukul Singh
相关产品推荐
相关产品推荐

