ElasticSearch:如何根据热门书籍数量提升作者排名
根据作者热门书籍数量排序的Elasticsearch查询优化
场景与需求
现有Author文档结构示例:
{ "name": "Author 1", "enabled": true, "books": [ {"name": "book1", "popular": true}, {"name": "book2", "popular": true}, {"name": "book3", "popular": false} ] }
需求为:筛选出enabled: true的作者,并根据其拥有的popular: true书籍数量进行排名,热门书籍越多,排名越靠前。
当前查询问题
当前使用的查询语句如下:
{ "query": { "bool": { "filter": { "term": {"enabled": true} }, "should": { "terms": { "books.popular": [true], "boost": 3 } } } } }
该查询仅能实现「只要作者有任意一本热门书籍,就获得固定3分权重提升」的效果,无法根据热门书籍的数量累加权重,不符合按数量排名的需求。
修改方案
方案1:针对非嵌套类型的books字段
使用function_score结合script_score脚本,直接统计热门书籍数量并加权:
{ "query": { "bool": { "filter": { "term": {"enabled": true} }, "must": [ { "function_score": { "functions": [ { "script_score": { "script": { "source": "doc['books.popular'].value.stream().filter(v -> v == true).count() * 3" } } } ], "boost_mode": "replace" } } ] } } }
- 脚本逻辑:统计
books.popular数组中值为true的元素个数,乘以权重系数3(可根据需求调整) boost_mode: "replace"表示用脚本计算的分数直接替换默认匹配分数,确保排名完全由热门书籍数量决定
方案2:针对嵌套类型的books字段
如果books字段在索引中定义为nested类型,需通过params._source访问原始文档数据:
{ "query": { "bool": { "filter": { "term": {"enabled": true} }, "must": [ { "function_score": { "functions": [ { "script_score": { "script": { "source": "params._source.books.stream().filter(b -> b.popular == true).count() * 3" } } } ], "boost_mode": "replace" } } ] } } }
- 嵌套类型下,
doc无法直接获取完整的数组结构,因此通过params._source读取原始文档中的books数组进行统计
内容的提问来源于stack exchange,提问作者Mojimi
相关产品推荐
相关产品推荐

