<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          哇,ElasticSearch多字段權(quán)重排序居然可以這么玩

          共 4647字,需瀏覽 10分鐘

           ·

          2020-08-25 12:24

          背景

          讀者提問:ES 的權(quán)重排序有沒有示列,參考參考?

          剛好之前也稍微接觸過,于是寫了這篇文章,可以簡單參考下。

          在很多復(fù)雜的業(yè)務(wù)場景下,排序的規(guī)則會比較復(fù)雜,單一的降序,升序無法滿足日常需求。不過 ES 中提供了給文檔加權(quán)重的方式來排序,還是挺好用的。

          首先初始化三條測試數(shù)據(jù),方便查看效果:

          {
          id: 1,
          title: "Java怎么學(xué)",
          type: 3,
          userId: 1,
          tags: [
          "java"
          ],
          textContent: "我要學(xué)Java",
          status: 1,
          heat: 80
          }
          {
          id: 2,
          title: "Java怎么學(xué)",
          type: 2,
          userId: 1,
          tags: [
          "java"
          ],
          textContent: "我要學(xué)Java",
          status: 1,
          heat: 99
          }
          {
          id: 3,
          title: "Java怎么學(xué)",
          type: 1,
          userId: 1,
          tags: [
          "java"
          ],
          textContent: "我要學(xué)Java",
          status: 1,
          heat: 100
          }

          type:1 為翻譯,2 為轉(zhuǎn)載,3 為原創(chuàng)

          需求是查詢 userId=1 的所有文章,按照熱度降序排序,但是原創(chuàng)類型的文章要顯示在前面,優(yōu)先級高于熱度。

          如果我們簡單的按照熱度排序的話,那么順序肯定是 id 為 3(熱度:100),2(熱度:99),1(熱度:80)這樣排列的。

          但是原創(chuàng)類型的要在前面,那么結(jié)果應(yīng)該是 1(熱度:80,類型:原創(chuàng)),3(熱度:100,類型:翻譯),2(熱度:99,類型:轉(zhuǎn)載)。

          排序條件肯定是以熱度來進(jìn)行的,這個是肯定的。唯一需要處理的就是怎么將原創(chuàng)類型的排在前面,如果只考慮實現(xiàn),方式還是有很多種的。

          比如:原創(chuàng)類型的熱度值可以調(diào)的比較高,但是呢,熱度值要重新弄一個字段,只用于排序,給用戶展示的還是之前的熱度值,這樣排序就簡單了,還是根據(jù)熱度排就可以實現(xiàn)效果。

          weightFactorFunction

          在 ES 搜索結(jié)果中_score 這個字段相信大家并不陌生,這是 ES 給出的評分,我們可以根據(jù)評分來排序,然后將原創(chuàng)類型的評分提高就可以實現(xiàn)想要的效果。

          直接看 Java 代碼吧,通過 FunctionScoreQueryBuilder 來構(gòu)建查詢。

          @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 searchResults = kittyRestHighLevelClient.search(searchRequest, ArticleDocument.class);
          searchResults.forEach(doc -> {
          System.out.println(doc.getId() + "\t" + doc.getType() + "\t" + doc.getHeat());
          });
          }

          通過 ScoreFunctionBuilders.weightFactorFunction 為文章類型設(shè)置對應(yīng)的權(quán)重,原創(chuàng)文章權(quán)重為 100,其他的都為 1,這樣原創(chuàng)文章的得分就高于其他類型的文章。

          在排序的時候優(yōu)先得分排序,然后熱度排序。就可以得到我們想要的結(jié)果了。

          scriptFunction

          除了使用 weightFactorFunction 來設(shè)置權(quán)重,另外介紹一種靈活度更高,適用于更復(fù)雜的排序場景的方式 scriptFunction。

          scriptFunction 允許我們通過腳本的方式來實現(xiàn)權(quán)重,直接看代碼:

          @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 searchResults = kittyRestHighLevelClient.search(searchRequest, ArticleDocument.class);
          searchResults.forEach(doc -> {
          System.out.println(doc.getId() + "\t" + doc.getType() + "\t" + doc.getHeat());
          });
          }

          scoreScript 就是控制權(quán)重的腳本,也就是一段代碼(腳本默認(rèn)是 groovy),是不是方便的多。

          關(guān)于作者:尹吉歡,簡單的技術(shù)愛好者,《Spring Cloud 微服務(wù)-全棧技術(shù)與案例解析》, 《Spring Cloud 微服務(wù) 入門 實戰(zhàn)與進(jìn)階》作者, 公眾號猿天地發(fā)起人。

          我整理了一份很全的學(xué)習(xí)資料,感興趣的可以微信搜索「猿天地」,回復(fù)關(guān)鍵字 「學(xué)習(xí)資料」獲取我整理好了的 Spring Cloud,Spring Cloud Alibaba,Sharding-JDBC 分庫分表,任務(wù)調(diào)度框架 XXL-JOB,MongoDB,爬蟲等相關(guān)資料。


          往期推薦



          一款直擊痛點的優(yōu)秀 HTTP 框架,讓我超高效完成了第三方接口的對接

          JetCache埋點的騷操作,不服不行啊

          給你的SpringBoot做埋點監(jiān)控--JVM應(yīng)用度量框架Micrometer

          居然說HikariCP連接池慢?是你不會用吧!

          簡直騷操作,ThreadLocal還能當(dāng)緩存用



          后臺回復(fù)?學(xué)習(xí)資料?領(lǐng)取學(xué)習(xí)視頻


          如有收獲,點個在看,誠摯感謝

          瀏覽 56
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费一级a毛一级a看免费视频下载 | 国产精品一卡二卡三卡四卡 | www.韩国三级 | 日皮视频在线播放 | 国产免费色网站视频 |