当前位置:网站首页>哇,ElasticSearch多字段权重排序居然可以这么玩
哇,ElasticSearch多字段权重排序居然可以这么玩
2020-11-06 01:28:23 【尹吉欢】
背景
读者提问:ES 的权重排序有没有示列,参考参考?
刚好之前也稍微接触过,于是写了这篇文章,可以简单参考下。
在很多复杂的业务场景下,排序的规则会比较复杂,单一的降序,升序无法满足日常需求。不过 ES 中提供了给文档加权重的方式来排序,还是挺好用的。
首先初始化三条测试数据,方便查看效果:
{
id: 1,
title: "Java怎么学",
type: 3,
userId: 1,
tags: [
"java"
],
textContent: "我要学Java",
status: 1,
heat: 80
}
{
id: 2,
title: "Java怎么学",
type: 2,
userId: 1,
tags: [
"java"
],
textContent: "我要学Java",
status: 1,
heat: 99
}
{
id: 3,
title: "Java怎么学",
type: 1,
userId: 1,
tags: [
"java"
],
textContent: "我要学Java",
status: 1,
heat: 100
}
type:1 为翻译,2 为转载,3 为原创
需求是查询 userId=1 的所有文章,按照热度降序排序,但是原创类型的文章要显示在前面,优先级高于热度。
如果我们简单的按照热度排序的话,那么顺序肯定是 id 为 3(热度:100),2(热度:99),1(热度:80)这样排列的。
但是原创类型的要在前面,那么结果应该是 1(热度:80,类型:原创),3(热度:100,类型:翻译),2(热度:99,类型:转载)。
排序条件肯定是以热度来进行的,这个是肯定的。唯一需要处理的就是怎么将原创类型的排在前面,如果只考虑实现,方式还是有很多种的。
比如:原创类型的热度值可以调的比较高,但是呢,热度值要重新弄一个字段,只用于排序,给用户展示的还是之前的热度值,这样排序就简单了,还是根据热度排就可以实现效果。
weightFactorFunction
在 ES 搜索结果中_score 这个字段相信大家并不陌生,这是 ES 给出的评分,我们可以根据评分来排序,然后将原创类型的评分提高就可以实现想要的效果。
直接看 Java 代码吧,通过 FunctionScoreQueryBuilder 来构建查询。
@Test
public void testSort() {
FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("type", 3), ScoreFunctionBuilders.weightFactorFunction(100)),
new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("type", 2), ScoreFunctionBuilders.weightFactorFunction(1)),
new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("type", 1), ScoreFunctionBuilders.weightFactorFunction(1))
};
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.must(QueryBuilders.termQuery("userId", 1));
FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(boolQuery, filterFunctionBuilders);
searchSourceBuilder.query(functionScoreQueryBuilder)
.sort("_score", SortOrder.DESC)
.sort("heat", SortOrder.DESC);
SearchRequest searchRequest = new SearchRequest(elasticSearchIndexConfig.getArticleSearchIndexName());
searchRequest.types(EsConstant.DEFAULT_TYPE);
searchRequest.source(searchSourceBuilder);
List<ArticleDocument> searchResults = kittyRestHighLevelClient.search(searchRequest, ArticleDocument.class);
searchResults.forEach(doc -> {
System.out.println(doc.getId() + "\t" + doc.getType() + "\t" + doc.getHeat());
});
}
通过 ScoreFunctionBuilders.weightFactorFunction 为文章类型设置对应的权重,原创文章权重为 100,其他的都为 1,这样原创文章的得分就高于其他类型的文章。
在排序的时候优先得分排序,然后热度排序。就可以得到我们想要的结果了。
scriptFunction
除了使用 weightFactorFunction 来设置权重,另外介绍一种灵活度更高,适用于更复杂的排序场景的方式 scriptFunction。
scriptFunction 允许我们通过脚本的方式来实现权重,直接看代码:
@Test
public void testSort() {
String scoreScript = "if (doc['type'].value == 3) {" +
" return 100;" +
"} else {" +
" return 1;" +
"}";
FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchAllQuery(), ScoreFunctionBuilders.scriptFunction(new Script(scoreScript)))
};
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.must(QueryBuilders.termQuery("userId", 1));
FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(boolQuery, filterFunctionBuilders);
searchSourceBuilder.query(functionScoreQueryBuilder)
.sort("_score", SortOrder.DESC)
.sort("heat", SortOrder.DESC);
SearchRequest searchRequest = new SearchRequest(elasticSearchIndexConfig.getArticleSearchIndexName());
searchRequest.types(EsConstant.DEFAULT_TYPE);
searchRequest.source(searchSourceBuilder);
List<ArticleDocument> searchResults = kittyRestHighLevelClient.search(searchRequest, ArticleDocument.class);
searchResults.forEach(doc -> {
System.out.println(doc.getId() + "\t" + doc.getType() + "\t" + doc.getHeat());
});
}
scoreScript 就是控制权重的脚本,也就是一段代码(脚本默认是 groovy),是不是方便的多。
关于作者:尹吉欢,简单的技术爱好者,《Spring Cloud 微服务-全栈技术与案例解析》, 《Spring Cloud 微服务 入门 实战与进阶》作者, 公众号猿天地发起人。
我整理了一份很全的学习资料,感兴趣的可以微信搜索「猿天地」,回复关键字 「学习资料」获取我整理好了的 Spring Cloud,Spring Cloud Alibaba,Sharding-JDBC 分库分表,任务调度框架 XXL-JOB,MongoDB,爬虫等相关资料。
版权声明
本文为[尹吉欢]所创,转载请带上原文链接,感谢
http://cxytiandi.com/blog/detail/36500
边栏推荐
- C++ 数字、string和char*的转换
- C++学习——centos7上部署C++开发环境
- C++学习——一步步学会写Makefile
- C++学习——临时对象的产生与优化
- C++学习——对象的引用的用法
- C++编程经验(6):使用C++风格的类型转换
- Won the CKA + CKS certificate with the highest gold content in kubernetes in 31 days!
- C + + number, string and char * conversion
- C + + Learning -- capacity() and resize() in C + +
- C + + Learning -- about code performance optimization
猜你喜欢
-
C + + programming experience (6): using C + + style type conversion
-
Latest party and government work report ppt - Park ppt
-
在线身份证号码提取生日工具
-
Online ID number extraction birthday tool
-
️野指针?悬空指针?️ 一文带你搞懂!
-
Field pointer? Dangling pointer? This article will help you understand!
-
HCNA Routing&Switching之GVRP
-
GVRP of hcna Routing & Switching
-
Seq2Seq实现闲聊机器人
-
【闲聊机器人】seq2seq模型的原理
随机推荐
- LeetCode 91. 解码方法
- Seq2seq implements chat robot
- [chat robot] principle of seq2seq model
- Leetcode 91. Decoding method
- HCNA Routing&Switching之GVRP
- GVRP of hcna Routing & Switching
- HDU7016 Random Walk 2
- [Code+#1]Yazid 的新生舞会
- CF1548C The Three Little Pigs
- HDU7033 Typing Contest
- HDU7016 Random Walk 2
- [code + 1] Yazid's freshman ball
- CF1548C The Three Little Pigs
- HDU7033 Typing Contest
- Qt Creator 自动补齐变慢的解决
- HALCON 20.11:如何处理标定助手品质问题
- HALCON 20.11:标定助手使用注意事项
- Solution of QT creator's automatic replenishment slowing down
- Halcon 20.11: how to deal with the quality problem of calibration assistant
- Halcon 20.11: precautions for use of calibration assistant
- “十大科学技术问题”揭晓!|青年科学家50²论坛
- "Top ten scientific and technological issues" announced| Young scientists 50 ² forum
- 求反转链表
- Reverse linked list
- js的数据类型
- JS data type
- 记一次文件读写遇到的bug
- Remember the bug encountered in reading and writing a file
- 单例模式
- Singleton mode
- 在这个 N 多编程语言争霸的世界,C++ 究竟还有没有未来?
- In this world of N programming languages, is there a future for C + +?
- es6模板字符
- js Promise
- js 数组方法 回顾
- ES6 template characters
- js Promise
- JS array method review
- 【Golang】️走进 Go 语言️ 第一课 Hello World
- [golang] go into go language lesson 1 Hello World