直接上代碼! { "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爲其它的一些業務查詢條件