直接上代码! { "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为其它的一些业务查询条件