elasticsearch乾貨:使用FunctionScore對文檔進行從新打分實例

直接上代碼!
{
  "function_score" : {
    "query" : {
      "bool" : {
        "must" : [
          {
            "term" : {
              "mediaType" : {
                "value" : 2,
                "boost" : 1.0
              }
            }
          },
          {
            "term" : {
              "status" : {
                "value" : 1,
                "boost" : 1.0
              }
            }
          }
        ],
        "adjust_pure_negative" : true,
        "boost" : 1.0
      }
    },
    "functions" : [
      {
        "filter" : {
          "match_all" : {
            "boost" : 1.0
          }
        },
        "script_score" : {
          "script" : {
            "source" : "(doc['countRead'].value+doc['countLike'].value+doc['countComment'].value)/3",          
            "lang" : "painless"
          }
        }
      }
    ],
    "score_mode" : "multiply",
    "boost_mode" : "multiply",
    "max_boost" : 3.4028235E38,
    "boost" : 1.0
  }
} 

"source" : "(doc['countRead'].value+doc['countLike'].value+doc['countComment'].value)/3", 
//表示以字段「countRead」,「countLike」,「countComment」 的平均值爲新的分數

spring data es的代碼實現以下:git

NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.must(QueryBuilders.termQuery("mediaType", ServiceConstant.MEDIA_VEDIO))
        .must(QueryBuilders.termQuery("status", ServiceConstant.ARTICLE_STATUS_PUBLISHED));
FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(boolQueryBuilder,ScoreFunctionBuilders.scriptFunction(
        new Script("(doc['countRead'].value+doc['countLike'].value+doc['countComment'].value)/3")))
        .scoreMode(FunctionScoreQuery.ScoreMode.MULTIPLY)
        .boostMode(FunctionScoreQueryBuilder.DEFAULT_BOOST_MODE);
System.out.println(functionScoreQueryBuilder);
nativeSearchQueryBuilder.withQuery(functionScoreQueryBuilder)
        .withPageable(PageRequest.of(PageUtil.getPage(param.getPage()) - 1, PageUtil.getPageSize(param.getPage_size())));
Page<ArticleEs> articlePage = articleEsRepository.search(nativeSearchQueryBuilder.build());

解析:functionScoreQuery由queryBuilder(業務查詢)和scriptFunction(自定義打分腳本)兩部分組成(上圖黃色部分),再把functionScoreQuery放入nativeSearchQueryBuilder中添加一些分頁參數便可(上面藍綠色部分);spring

參考資料:FunctionScoreless

10/16:最近根據業務寫搜索接口,要根據用戶位置信息,商品發佈時間,評分,是否推薦這幾個屬性綜合排序,也就是說要用不一樣的函數對文檔從新打分:函數

{
  "query": {
    "function_score": {
      "query": {
        "match_all": {}
      },//這裏是業務搜索語句
      "functions": [
        {
          "filter": {
            "term": {
              "recommended": "1"
            }
          },
          "weight": 2
        },//這裏表示:若是是推薦商品則權重設置爲2
        {
          "gauss": {
            "location": {
              "origin": {
                "lat": 23.0932922,
                "lon": 113.4052734
              },
              "offset": "10km",
              "scale": "1km"
            }
          },
          "weight": 3
        },//這裏的高斯函數表示:以origin點爲中心,offset爲半徑的範圍內的爲最佳匹配結果,每超過scale公里配分就降低
        {
          "linear": {
            "score": {
              "origin": 8.5,
              "offset": 1.5,
              "scale": 2
            }
          },
          "weight": 2
     },//這裏linear函數和guass函數相似(只是曲線不一樣而已)以8.5爲圓點,上下1.5分的範圍也就是7-10分爲最佳匹配,每低於2分降低(score爲es字段,表示商品分)
        {
          "gauss": {
            "createTime": {
              "origin": "2019-10-15T10:24:32+08:00",
              "offset": "5d",
              "scale": "5d"
            }
          },
          "weight": 2
        }//以origin這個時間點爲中心,先後五天的範圍內爲最佳,沒超過5天評分就降低
      ],
      "score_mode": "sum",                //score_mode表示對上面幾個函數處理得出的子分數如何處理,這裏是相加得出一個總分數;
      "boost_mode": "multiply"            //boost_mode表示上一步得出的總分數與原分數之間如何處理,這裏是兩個分數相乘獲得最後一個分數
    }
  }
}

data es 代碼以下ui

//構造FunctionScore
private FunctionScoreQueryBuilder  getFilterFunctionBuilders(BoolQueryBuilder boolQueryBuilder,Double latitude,Double longitude){
    FunctionScoreQueryBuilder.FilterFunctionBuilder[] filterFunctionBuilders = new FunctionScoreQueryBuilder.FilterFunctionBuilder[4];
    //filter打分
    FunctionScoreQueryBuilder.FilterFunctionBuilder filterFunctionBuilder=new     FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("recommended", 1),new WeightBuilder().setWeight(2));
    filterFunctionBuilders[0]=filterFunctionBuilder;
    //距離打分
    Map locationMap=new HashMap();
    locationMap.put("lat",latitude);
    locationMap.put("lon",longitude);
    GaussDecayFunctionBuilder distanceGaussDecayFunctionBuilder=ScoreFunctionBuilders
            .gaussDecayFunction("location",locationMap, "1km", "5km").setWeight(3);
    filterFunctionBuilders[1]=new FunctionScoreQueryBuilder.FilterFunctionBuilder(distanceGaussDecayFunctionBuilder);
    //評分打分
    LinearDecayFunctionBuilder ScoreLinearDecayFunctionBuilder=ScoreFunctionBuilders.linearDecayFunction("score", 8.5, 1, 1.5).setWeight(2);
    filterFunctionBuilders[2]=new FunctionScoreQueryBuilder.FilterFunctionBuilder(ScoreLinearDecayFunctionBuilder);
    //日期打分
    GaussDecayFunctionBuilder dateGaussDecayFunctionBuilder=ScoreFunctionBuilders.gaussDecayFunction("createTime", new Date(), "5d", "5d").setWeight(2);
    filterFunctionBuilders[3]=new FunctionScoreQueryBuilder.FilterFunctionBuilder(dateGaussDecayFunctionBuilder);
    FunctionScoreQueryBuilder functionScoreQueryBuilder= QueryBuilders.functionScoreQuery(boolQueryBuilder,filterFunctionBuilders)
            .scoreMode(FunctionScoreQuery.ScoreMode.SUM)
            .boostMode(CombineFunction.SUM);
    return functionScoreQueryBuilder;
} //最後構造完FunctionScore須要放入NativeSearchQueryBuilder中,參數boolQueryBuilder爲其它的一些業務查詢條件
相關文章
相關標籤/搜索