You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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"}}]
              }
            }
          }
        }
      }
    }
  }
}

说明:

  1. 外层filters聚合区分两种匹配类型的结果;
  2. 内层by_entity_type按类型聚合;
  3. 分别用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"}}
            }
          }
        }
      }
    }
  }
}

说明:

  1. 先按entity_type做顶层聚合;
  2. 每个类型桶内,分别用带过滤条件的top_hits聚合,获取对应匹配结果并按要求排序;
  3. 此方案无需外层区分匹配类型,直接在类型桶内拆分结果。

内容的提问来源于stack exchange,提问作者Mukul Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 01:06:19