介绍:
1、function_score是可以修改查询检索文档的分数,使用function_score必须定义一个查询和一个或多个函数,为查询返回的每个文档计算一个新的分数。
function_score提供的评分函数:
1、weight : 设置一个float类型的权重值,使最终分数是查询分数与该权重值的乘积
2、field_value_factor : 允许使用文档中的字段来影响分数
GET /_search
{
"query": {
"function_score": {
"field_value_factor": {
"field": "my-int",
"factor": 1.2,
"modifier": "sqrt",
"missing": 1
}
}
}
}
field:要从文档中提取的字段(相乘的字段,该字段必须是数字类型)。
factor:与字段值相乘的可选因子,默认为1。
modifier:应用于字段值的修饰符,可以是以下之一:none、log、 log1p、log2p、ln、ln1p、ln2p、square、sqrt、 或reciprocal。默认为none(参考官网解释:这里)
3、random_score : 为每个用户都使用一个不同的随机评分
4、decay functions(衰减函数,如:linear、exp、guass):以某个字段的值为基准,距离某个值越近得分越高
5、script_score : 自定义脚本函数控制评分计算
function_score参数解释:
1、boost_mode : 决定查询分数和评分函数计算出来的分数如何合并,默认相乘(multiply,sum,min,max,replace)
2、score_mode : 决定functions里面的评分函数之间的分数如何合并,默认相乘(multiply,sum,min,max,avg,first(使用首个函数))
function_socre查询模板:
1、单个评分函数:
GET /_search
{
"query": {
"function_score": {
"query": {.....}, //主查询,查询完后这裡自己会有一个评分,就是查询分数
"field_value_factor": {...}, //在查询分数的基础上,给他加上评分函数计算出来的分数,如果只有一个评分函数时,直接将评分函数写在query下面就可以了
"boost_mode": "multiply", //決定查询分数和评分函数分数怎么合并
"max_boost": 1.5 //限制评分函数计算出来的最高分,但是不会限制查询分数
}
}
}
2、多个评分函数(用functions包含这些函数)
GET /_search
{
"query": {
"function_score": {
"query": { "match_all": {} },
"functions": [
{
"filter": { "match": { "test": "bar" } },
"random_score": {},
"weight": 23
},
{
"filter": { "match": { "test": "cat" } },
"weight": 42
},
{
"script_score": {
"script": {
"source": "Math.log(2 + doc['my-int'].value)"
}
}
}
],
"max_boost": 42,
"score_mode": "max",
"boost_mode": "multiply",
"min_score": 42
}
}
}
特别注意:
1、如果查询条件中存在距离过滤的,查询分数为0,如果不指定boost_mode的分数合并方式(默认相乘),则计算出来的分数都是0,如下:(纠正一下,无意间看到一篇文章说“在一个查询语句里面可以同时存在query
和filter
,只不过只有query
的查询字段会进行相关性_score
的计算,而filter
仅仅用来筛选”,所以这里造成查询分时为0并不是filter的原因,而是must:[]的原因)
{
"query":{
"function_score":{
"query":{
"bool":{
"must":[],
"filter":{
"geo_distance":{
"distance":"200km",
"location":{
"lat":23.31231,
"lon":120.231231
}
}
}
}
},
"functions":[
{
"filter":{"match":{"test": "bar"}},
"weight":20
},
{
"script_score":{
"script":{
"lang":"painless",
"params":{"value":20},
"inline":"Math.log(2 + doc['my-int'].value*params.value)"
}
}
}
],
"score_mode":"sum"
//"boost_mode":"sum"
}
},
"from":0,
"size":5,
"sort" : [{"_score" : "asc" }],
"explain": true
}
结果:
2、ES6.5版本之后(本文对应的es版本是7.10),weight不能为负值,且如果评分函数计算出来的值为负数,ES会自动过滤掉对应的数据。
3、Elasticsearch中,内置了很多分词器(analyzers),默认是standard 分词器