前言
之前做一个歌曲搜索功能,产品有这样的一个需求 如果两者搜索分值相同,点击次数多的排在前面
实现这个功能当然是使用es提供的function_score功能了,废话不多说,放码
使用function_score实现自定义分值
rest请求如下
GET /{index}/{type}/_search?explain
{
"query": {
"function_score": {
"query": {
你的查询语句
},
"field_value_factor": {
"field": "字段",
"modifier": "log1p",
"factor": 0.1
},
"boost_mode": "sum"
}
},
"sort": {
"_score": {
"order": "desc"
}
}
}
复制代码
这里的“字段”存储了这个doc被点击的次数 以上脚本实现了搜索结果自定义分值 最终的分数=_score+log(1+字段的值)
"field_value_factor": {
"field": "字段",
"modifier": "log1p",
"factor": 0.1
},
"boost_mode": "sum"
复制代码
- field 设置用来计算的字段
- modifier 用来设置计算方式
- factor 设置因子
- boost_mode 设置最终得分的计算方式
具体含义请看官方
附上java实现
SearchRequestBuilder searchRequestBuilder = esClient.client
.prepareSearch({index}).setTypes({type});
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
.should(QueryBuilders.matchPhraseQuery("name", keyWord));
Map<String, Object> params = new HashMap<>();
FieldValueFactorFunctionBuilder fieldQuery = new FieldValueFactorFunctionBuilder(
"score");
// 额外分数=log(1+score)
fieldQuery.factor(0.1f);
fieldQuery.modifier(FieldValueFactorFunction.Modifier.LOG1P);
// 最终分数=_score+额外分数
FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders
.functionScoreQuery(queryBuilder, fieldQuery)
.boostMode(CombineFunction.SUM);
//根据分值倒序排列
searchRequestBuilder.addSort("_score", SortOrder.DESC);
searchRequestBuilder.setQuery(functionScoreQueryBuilder);
//设置获取位置个数
searchRequestBuilder.setFrom(0).setSize(100);
//设置查询分片,防止震荡问题,生产中可以用 用户id 填入,对同一个用户保证多次查询结果相同
searchRequestBuilder.setPreference("233");
复制代码