如何配置ElasticSearch使其计算词频权重时兼顾双字段?
解决ElasticSearch文档排序权重问题的方案
针对你遇到的ArticleTest类型文档因标签匹配权重机制,始终排在匹配度更高的ArticleBasic文档之前的问题,有以下几种可配置的解决方案:
1. 给不同类型的标签查询设置差异化权重(Boost)
直接在ArticleBasic的标签匹配查询中添加boost参数,提升这类查询的得分权重,让匹配更多标签的ArticleBasic文档能获得更高的总分,超过ArticleTest文档。
修改后的查询示例:
{ "query": { "bool": { "should": [ { "term": { "contenttype": "ArticleTest" } }, { "term": { "contenttype": "ArticleBasic" } } ], "must": [ { "bool": { "should": [ { "wildcard": { "ArticleBasic.tags": "*history*", "boost": 2 } }, { "wildcard": { "ArticleBasic.tags": "*meet locals*", "boost": 2 } }, { "wildcard": { "ArticleBasic.tags": "*nature & wildlife*", "boost": 2 } }, { "wildcard": { "ArticleBasic.tags": "*|north-america|canada|quebec-city*", "boost": 2 } }, { "wildcard": { "ArticleBasic.tags": "*|north-america|canada|churchill*", "boost": 2 } }, { "wildcard": { "ArticleBasic.tags": "*|north-america|canada|manitoba*", "boost": 2 } }, { "wildcard": { "ArticleBasic.tags": "*|north-america|canada|alberta*", "boost": 2 } }, { "wildcard": { "ArticleTest.tags": "*history*" } }, { "wildcard": { "ArticleTest.tags": "*meet locals*" } }, { "wildcard": { "ArticleTest.tags": "*nature & wildlife*" } }, { "wildcard": { "ArticleTest.tags": "*|north-america|canada|quebec-city*" } }, { "wildcard": { "ArticleTest.tags": "*|north-america|canada|churchill*" } }, { "wildcard": { "ArticleTest.tags": "*|north-america|canada|manitoba*" } }, { "wildcard": { "ArticleTest.tags": "*|north-america|canada|alberta*" } } ] } } ], "filter": [ { "bool": { "must_not": [{ "match": { "identifier": "b05e28402b854b9221f08daa81e99b61" } }] } } ] } }, "sort": [ { "_score": "desc" }, { "_script": { "type": "number", "script": "if(doc['ArticleTest.publish'].size() != 0) { return doc['ArticleTest.publish'].value.millis; }else if(doc['ArticleBasic.publish'].size() != 0) { return doc['ArticleBasic.publish'].value.millis; }else { return 0; }", "order": "desc" } } ], "size": 5, "from": 0 }
这里给所有ArticleBasic的标签查询设置了boost:2,意味着每个匹配的得分会是原来的2倍,你可以根据实际情况调整这个数值。
2. 使用function_score自定义得分逻辑
如果需要更灵活的权重计算,可以用function_score查询,结合文档类型和标签匹配情况自定义得分。比如给ArticleBasic文档设置基础权重乘数,同时保留标签匹配的得分累加:
示例查询:
{ "query": { "function_score": { "query": { "bool": { "must": [ { "bool": { "should": [ { "wildcard": { "ArticleBasic.tags": "*history*" } }, { "wildcard": { "ArticleBasic.tags": "*meet locals*" } }, { "wildcard": { "ArticleBasic.tags": "*nature & wildlife*" } }, { "wildcard": { "ArticleBasic.tags": "*|north-america|canada|quebec-city*" } }, { "wildcard": { "ArticleBasic.tags": "*|north-america|canada|churchill*" } }, { "wildcard": { "ArticleBasic.tags": "*|north-america|canada|manitoba*" } }, { "wildcard": { "ArticleBasic.tags": "*|north-america|canada|alberta*" } }, { "wildcard": { "ArticleTest.tags": "*history*" } }, { "wildcard": { "ArticleTest.tags": "*meet locals*" } }, { "wildcard": { "ArticleTest.tags": "*nature & wildlife*" } }, { "wildcard": { "ArticleTest.tags": "*|north-america|canada|quebec-city*" } }, { "wildcard": { "ArticleTest.tags": "*|north-america|canada|churchill*" } }, { "wildcard": { "ArticleTest.tags": "*|north-america|canada|manitoba*" } }, { "wildcard": { "ArticleTest.tags": "*|north-america|canada|alberta*" } } ] } } ], "filter": [ { "bool": { "must_not": [{ "match": { "identifier": "b05e28402b854b9221f08daa81e99b61" } }] } }, { "bool": { "should": [ { "term": { "contenttype": "ArticleTest" } }, { "term": { "contenttype": "ArticleBasic" } } ] } } ] } }, "functions": [ { "filter": { "term": { "contenttype": "ArticleBasic" } }, "weight": 1.5 }, { "filter": { "term": { "contenttype": "ArticleTest" } }, "weight": 1.0 } ], "score_mode": "multiply" } }, "sort": [ { "_score": "desc" }, { "_script": { "type": "number", "script": "if(doc['ArticleTest.publish'].size() != 0) { return doc['ArticleTest.publish'].value.millis; }else if(doc['ArticleBasic.publish'].size() != 0) { return doc['ArticleBasic.publish'].value.millis; }else { return 0; }", "order": "desc" } } ], "size": 5, "from": 0 }
这里通过weight参数给ArticleBasic文档设置了1.5倍的得分乘数,ArticleTest保持1倍,最终得分是标签匹配的原始得分乘以这个权重。score_mode设置为multiply表示权重与原始得分相乘,你也可以根据需求选择sum等其他模式。
3. 优化标签字段的索引(长期方案)
当前使用wildcard查询标签字段效率低,且得分计算不够精准。建议将tags字段拆分为多值keyword字段:
- 修改索引映射,将
ArticleBasic.tags和ArticleTest.tags设置为type: keyword且multi: true(或者预先按|拆分存储为数组)。 - 查询时使用
terms或match查询替代wildcard,这样每个标签匹配的得分计算更准确,也更容易通过boost调整权重。
例如,拆分后的标签字段查询可以改为:
{ "terms": { "ArticleBasic.tags": ["history", "meet locals", "nature & wildlife", "north-america|canada|quebec-city"], "boost": 2 } }
这种方式不仅查询效率更高,得分计算也更符合预期。
内容的提问来源于stack exchange,提问作者Jmh2013
相关产品推荐
相关产品推荐

