如何在Elasticsearch查询中指定特定字段的结果项占比?
Elasticsearch 按指定比例返回不同类型文档实现方案
完全可以实现你要的比例控制,常用有两种方案,可根据你的场景选择:
方案一:filter聚合+top_hits 实现严格比例控制(推荐)
该方案可以100%保证返回结果的占比符合要求,以你需要的20条总结果为例,会严格返回16条manager、4条lead,只要两类文档的库存量足够就不会出现偏差。
示例查询:
{ "size": 0, "query": { "terms": { "type": ["manager", "lead"] } }, "aggs": { "manager_results": { "filter": { "term": { "type": "manager" } }, "aggs": { "top_manager": { "top_hits": { "size": 16, "from": 0, "_source": "*" } } } }, "lead_results": { "filter": { "term": { "type": "lead" } }, "aggs": { "top_lead": { "top_hits": { "size": 4, "from": 0, "_source": "*" } } } } } }
说明:
- 你可以根据需要的总返回条数,动态调整两个
top_hits下的size值,比如总返回100条就设manager为80、lead为20 - 如果需要分页,调整对应
from参数的值即可,业务侧拿到聚合结果后自行拼接两类文档返回 - 若你的
type字段为text类型,需要把查询字段替换为type.keyword避免匹配异常
方案二:function_score 加权实现近似比例
如果不需要严格控制比例,仅需整体结果大致符合8:2的占比,可以选择该方案,不需要业务侧做额外的结果拼装,分页逻辑和普通查询完全一致。
示例查询:
{ "from": 0, "size": 20, "query": { "bool": { "should": [ { "function_score": { "query": { "term": { "type": "manager" } }, "weight": 4 } }, { "function_score": { "query": { "term": { "type": "lead" } }, "weight": 1 } } ] } } }
说明:
- 这里给manager类型文档设置4倍权重、lead设置1倍权重,两者得分比例为4:1,排序后返回的结果会大致符合80%、20%的占比
- 缺点是占比为近似值,受实际文档得分、两类文档总量影响,无法100%保证精确比例
内容的提问来源于stack exchange,提问作者Maucan
相关产品推荐
相关产品推荐

