当前位置:网站首页>Wow, elasticsearch multi field weight sorting can play like this

Wow, elasticsearch multi field weight sorting can play like this

2020-11-06 01:28:23 Yin Jihuan

background

Readers ask questions :ES There is no list of the weight ranking of the , Reference ?

I've been in touch with , So I wrote this article , It can be referred to as .

In many complex business scenarios , The rules of sorting will be more complicated , A single descending order , Ascending order can't meet daily needs . however ES Provides a way to weight documents to sort , It still works .

First initialize three test data , Easy to view :

  
  1. {
  2. id: 1,
  3. title: "Java How to learn ",
  4. type: 3,
  5. userId: 1,
  6. tags: [
  7. "java"
  8. ],
  9. textContent: " I have to learn Java",
  10. status: 1,
  11. heat: 80
  12. }
  13. {
  14. id: 2,
  15. title: "Java How to learn ",
  16. type: 2,
  17. userId: 1,
  18. tags: [
  19. "java"
  20. ],
  21. textContent: " I have to learn Java",
  22. status: 1,
  23. heat: 99
  24. }
  25. {
  26. id: 3,
  27. title: "Java How to learn ",
  28. type: 1,
  29. userId: 1,
  30. tags: [
  31. "java"
  32. ],
  33. textContent: " I have to learn Java",
  34. status: 1,
  35. heat: 100
  36. }

type:1 For translation ,2 For reprint ,3 For the original

The requirement is to query userId=1 All articles of , Sort in descending order of heat , But the original type of article should be displayed in the front , Priority over heat .

If we simply sort by heat , So the order must be id by 3( degree of heat :100),2( degree of heat :99),1( degree of heat :80) It's arranged like this .

But the original type should be at the front , So the result should be 1( degree of heat :80, type : original ),3( degree of heat :100, type : translate ),2( degree of heat :99, type : Reprint ).

The sorting conditions must be in terms of heat , This is for sure . The only thing that needs to be dealt with is how to put the original type at the top , If only implementation is considered , There are many ways .

such as : The original type of heat value can be adjusted higher , But what? , The heat value needs a new field , Only for sorting , It shows the user the same heat value as before , This makes sorting simple , Or according to the heat arrangement can achieve the effect .

weightFactorFunction

stay ES In search results _score I believe you are not unfamiliar with this field , This is a ES The score given , We can sort by score , Then improve the score of the original type to achieve the desired effect .

Look directly at Java Code it , adopt FunctionScoreQueryBuilder To build the query .

  
  1. @Test
  2. public void testSort() {
  3. FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
  4. new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("type", 3), ScoreFunctionBuilders.weightFactorFunction(100)),
  5. new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("type", 2), ScoreFunctionBuilders.weightFactorFunction(1)),
  6. new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchQuery("type", 1), ScoreFunctionBuilders.weightFactorFunction(1))
  7. };
  8. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  9. BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
  10. boolQuery.must(QueryBuilders.termQuery("userId", 1));
  11. FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(boolQuery, filterFunctionBuilders);
  12. searchSourceBuilder.query(functionScoreQueryBuilder)
  13. .sort("_score", SortOrder.DESC)
  14. .sort("heat", SortOrder.DESC);
  15. SearchRequest searchRequest = new SearchRequest(elasticSearchIndexConfig.getArticleSearchIndexName());
  16. searchRequest.types(EsConstant.DEFAULT_TYPE);
  17. searchRequest.source(searchSourceBuilder);
  18. List<ArticleDocument> searchResults = kittyRestHighLevelClient.search(searchRequest, ArticleDocument.class);
  19. searchResults.forEach(doc -> {
  20. System.out.println(doc.getId() + "\t" + doc.getType() + "\t" + doc.getHeat());
  21. });
  22. }

adopt ScoreFunctionBuilders.weightFactorFunction Set the corresponding weight for the article type , The weight of original article is 100, Everything else 1, In this way, the score of original articles is higher than that of other types of articles .

In order to rank, the score should be ranked first , Then the heat is sorted . We can get the results we want .

scriptFunction

Besides using weightFactorFunction To set the weight , In addition, it introduces a kind of higher flexibility , For more complex sorting scenarios scriptFunction.

scriptFunction It allows us to achieve weights through scripting , Look directly at the code :

  
  1. @Test
  2. public void testSort() {
  3. String scoreScript = "if (doc['type'].value == 3) {" +
  4. " return 100;" +
  5. "} else {" +
  6. " return 1;" +
  7. "}";
  8. FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
  9. new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.matchAllQuery(), ScoreFunctionBuilders.scriptFunction(new Script(scoreScript)))
  10. };
  11. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  12. BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
  13. boolQuery.must(QueryBuilders.termQuery("userId", 1));
  14. FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(boolQuery, filterFunctionBuilders);
  15. searchSourceBuilder.query(functionScoreQueryBuilder)
  16. .sort("_score", SortOrder.DESC)
  17. .sort("heat", SortOrder.DESC);
  18. SearchRequest searchRequest = new SearchRequest(elasticSearchIndexConfig.getArticleSearchIndexName());
  19. searchRequest.types(EsConstant.DEFAULT_TYPE);
  20. searchRequest.source(searchSourceBuilder);
  21. List<ArticleDocument> searchResults = kittyRestHighLevelClient.search(searchRequest, ArticleDocument.class);
  22. searchResults.forEach(doc -> {
  23. System.out.println(doc.getId() + "\t" + doc.getType() + "\t" + doc.getHeat());
  24. });
  25. }

scoreScript It's the script that controls the weight , That is, a piece of code ( The default script is groovy), Is it convenient to do so much .

About author : Yin Jihuan , Simple technology enthusiasts ,《Spring Cloud Microservices - Full stack technology and case analysis 》, 《Spring Cloud Microservices introduction Actual combat and advanced 》 author , official account Ape world Originator .

I have compiled a complete set of learning materials , Those who are interested can search through wechat 「 Ape world 」, Reply key 「 Learning materials 」 Get what I've sorted out Spring Cloud,Spring Cloud Alibaba,Sharding-JDBC Sub database and sub table , Task scheduling framework XXL-JOB,MongoDB, Reptiles and other related information .

版权声明
本文为[Yin Jihuan]所创,转载请带上原文链接,感谢