最近做新闻推荐系统,新闻搜索采用的是elasticsearch引擎,为了使推荐更接近用户偏好,搜索时使用了function_score功能对文档进行了重新打分,改变排序规则。以下介绍关于function score的一些用法。
The function_score
allows you to modify the score of documents that are retrieved by a query. This can be useful if, for example, a score function is computationally expensive and it is sufficient to compute the score on a filtered set of documents.(这个是官方对function_score的解释)
es内置了几种预先定义好了的函数:
1、weight:对每份文档适用一个简单的提升,且该提升不会被归约:当weight为2时,结果为2 * _score。
2、field_value_factor:使用文档中某个字段的值来改变_score,比如将受欢迎程度或者投票数量考虑在内。
3、random_score:使用一致性随机分值计算来对每个用户采用不同的结果排序方式,对相同用户仍然使用相同的排序方式。
4、Decay Functions:衰减函数,衰减函数是利用从给定的原点到某个用户数字类型字段的值的距离的衰减进行打分的。这类似于一个范围查询,而且边缘是光滑的。
es内部支持的衰减函数有gauss(高斯)、exp(指数)、linear(线性)
5、 script_score:使用自定义的脚本来完全控制分值计算逻辑。
推荐系统中有很多个性化的feature权重,所以我们主要采用script_score来对文档打分。下面主要说一下script_score的使用。
(1)、在es配置中配置脚本功能,配置后重启服务
script.inline: on
script.enfine.groovy.inline.aggs: on
script.indexed: on
script.file: on
(2)、测试查询语句,例:
{"query": {
"function_score": {
"query": {
"bool": {
"should": [
{
"match": {
"title": "航母"
}
}
]
}
},
"score_mode": "first",
"script_score": {
"lang": "groovy",
"params": {
"timestamp": 1460768418541
},
"script": "(_score+ 1/(timestamp-doc['timestamp'].value.toDouble()+1))/2"
},
"boost_mode": "replace"
}
}
}
- 查询结果中可以看到每条文档数据的分值 例:"_score": 0.5103256,
- (3)、java查询代码 queryBuilder:
Map<String,Object> params = new HashMap<String,Object>(); params.put("timestamp",1460768428541L); FunctionScoreQueryBuilder query = QueryBuilders.functionScoreQuery(QueryBuilders.boolQuery() .should(QueryBuilders.matchQuery("title", "航母")) ).add(ScoreFunctionBuilders.scriptFunction( new Script("(_score + 1/(timestamp-doc['timestamp'].value.toDouble()+1))/2" ,ScriptType.INLINE,"groovy",params)) ).scoreMode("first") .boostMode(CombineFunction.REPLACE);
- "script_score": {
"lang": "groovy",
"params": {
"timestamp": 1460768418541
},
"script": "(_score+ 1/(timestamp-doc['timestamp'].value.toDouble()+1))/2"
},
- 以上这部分就是脚本函数打分的一个实现。lang表示选用的脚本语言,这里我们选用groovy(es配置,默认groovy);params是脚本函数需要的参数;script是函数语句(参照groovy语法)