ES自定义评分机制:function_score查询详解

简介: ES自定义评分机制:function_score查询详解

一、function_score介绍


主要用于让用户自定义查询相关性得分,实现精细化控制评分的目的。


在ES的常规查询中,只有参与了匹配查询的字段才会参与记录的相关性得分score的计算。但很多时候我们希望能根据搜索记录的热度、浏览量、评分高低等来计算相关性得分,提高用户体验。


官网介绍:function_score


哪些信息是用户真正关心的?

搜索引擎本质是一个匹配过程,即从海量数据中找到匹配用户需求的内容。


98.png


除了根据用户输入的查询关键字去检索外,还应根据用户的使用习惯、浏览记录、最近关注、搜索记录的热度等进行更加智能化的匹配。


常见的一些场景:

1、在百度、谷歌中搜索内容;

2、在淘宝、京东上面搜索商品;

3、在抖音上搜索用户和短视频。


二、实战演示


1、创建索引

说明:创建博客blog索引,只有2个字段,博客名title和访问量access_num。

用户根据博客名称搜索的时候,既希望名称能尽可能匹配,也希望访问量越多的排在最前面,因为一般访问量越多的博客质量会越好,这样可以提高用户的检索体验。

DELETE /blog
PUT /blog
{  
  "mappings": {
     "properties": {
      "title": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart"
      },
      "access_num": {
        "type": "integer"
      }
    }
  }
}

2、添加测试数据

PUT blog/_doc/2
{
  "title": "java入门到精通",
  "access_num":30
}
PUT blog/_doc/3
{
  "title": "es入门到精通",
  "access_num":50
}
PUT blog/_doc/4
{
  "title": "mysql入门到精通",
  "access_num":30
}
PUT blog/_doc/5
{
  "title": "精通spark",
  "access_num":40
}


3、常规检索

直接使用match查询,只会根据检索关键字和title字段值的相关性检索排序。


GET /blog/_search
{
    "query": {
       "match": {
                    "title": "java入门"
                }
    }
}

查询结果L

"hits" : [
      {
        "_index" : "blog",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.3739232,
        "_source" : {
          "title" : "java入门",
          "access_num" : 20
        }
      },
      {
        "_index" : "blog",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0552295,
        "_source" : {
          "title" : "java入门到精通",
          "access_num" : 30
        }
      },
      ……
     ]


4、采用function_score自定义评分

除了match匹配查询计算相关性得分,还引入了根据浏览量access_num计算得分。

GET /blog/_search
{
    "query": {
        "function_score": {
            "query": {
                "match": {
                    "title": "java入门"
                }
            },
            "functions": [
                {
                    "script_score": {
                        "script": {
                            "params": {
                                "access_num_ratio": 2.5
                            },
                            "lang": "painless",
                            "source": "doc['access_num'].value * params.access_num_ratio "
                        }
                    }
                }
            ]
        }
    }
}


查询结果:

说明:尽管博客名为java入门的名称和搜索词更加匹配,但由于博客名为java入门到精通的博客访问量更高,最终检索品分更高,排名更靠前。


"hits" : [
      {
        "_index" : "blog",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 79.14222,
        "_source" : {
          "title" : "java入门到精通",
          "access_num" : 30
        }
      },
      {
        "_index" : "blog",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 68.69616,
        "_source" : {
          "title" : "java入门",
          "access_num" : 20
        }
      },


三、自定义评分类型


function_score 查询提供了多种类型的评分函数。


script_score script脚本评分

weight 字段权重评分

random_score 随机评分

field_value_factor 字段值因子评分

decay functions: gauss, linear, exp 衰减函数

说明:

decay functions衰减函数太过复杂,这里暂时不作介绍。


1、script脚本评分

script_score 函数允许您包装另一个查询并选择性地使用脚本表达式从文档中的其他数字字段值派生的计算自定义它的评分。 这是一个简单的示例:

GET /_search
{
    "query": {
        "function_score": {
            "query": {
                "match": { "message": "elasticsearch" }
            },
            "script_score" : {
                "script" : {
                  "source": "Math.log(2 + doc['likes'].value)"
                }
            }
        }
    }
}


请注意,与 custom_score 查询不同,查询的分数乘以脚本评分的结果。 如果你想禁止这个,设置 “boost_mode”: “replace”


2、weight 权重评分

GET /_search
{
    "query": {
        "function_score": {
            "query": {
                "match": { "message": "elasticsearch" }
            },
            "functions":[
              {
              "weight":1.5  ,
              "filter": { "term": { "description": "hadoop" }}   
              },
              {
              "weight":3  ,
              "filter": { "term": { "description": "flink" }}   
              }
            ]
        }
    }
}

weight函数是最简单的分支,它将得分乘以一个常数。请注意,普通的boost字段按照标准化来增加分数。

而weight函数却真真切切地将得分乘以确定的数值。


下面的例子意味着,在description字段中匹配了hadoop词条查询的文档,他们的分数将被乘以1.5.



3、random_score随机评分

random_score 生成从 0 到但不包括 1 的均匀分布的分数。默认情况下,它使用内部 Lucene doc id 作为随机源。


如果您希望分数可重现,可以提供种子和字段。 然后将基于此种子、所考虑文档的字段最小值以及基于索引名称和分片 id 计算的盐计算最终分数,以便具有相同值但存储在不同索引中的文档得到 不同的分数。


请注意,位于同一个分片内且具有相同字段值的文档将获得相同的分数,因此通常希望使用对所有文档具有唯一值的字段。 一个好的默认选择可能是使用 _seq_no 字段,其唯一的缺点是如果文档更新,分数会改变,因为更新操作也会更新 _seq_no 字段的值。

GET /_search
{
    "query": {
        "function_score": {
            "random_score": {
                "seed": 10,
                "field": "_seq_no"
            }
        }
    }
}


4、field_value_factor 字段值因子评分

field_value_factor 函数允许您使用文档中的字段来影响分数。 它类似于使用 script_score 函数,但是,它避免了脚本的开销。 如果用于多值字段,则在计算中仅使用该字段的第一个值。


举个例子,假设你有一个用数字 likes 字段索引的文档,并希望用这个字段影响文档的分数,一个这样做的例子看起来像:


GET /_search
{
    "query": {
        "function_score": {
            "field_value_factor": {
                "field": "likes",
                "factor": 1.2,
                "modifier": "sqrt",
                "missing": 1
            }
        }
    }
}


得分计算公式: sqrt(1.2 * doc['likes'].value)


参数说明:


field

要从文档中提取的字段。


factor

与字段值相乘的可选因子,默认为 1。


modifier

应用于字段值的计算修饰符, none, log, log1p, log2p, ln, ln1p, ln2p, square, sqrt, or reciprocal,默认 none.


missing

如果文档没有该字段,则使用的值。 修饰符和因子仍然适用于它,就好像它是从文档中读取的一样。


5、Decay functions 衰减函数

衰减函数使用一个函数对文档进行评分,该函数根据文档的数字字段值与用户给定原点的距离而衰减。 这类似于范围查询,但具有平滑的边缘而不是框。


要对具有数字字段的查询使用距离评分,用户必须为每个字段定义原点和比例。 需要原点来定义计算距离的“中心点”,以及定义衰减率的比例尺。


好吧,一脸懵逼,这里就不继续介绍了。


放一个示例,大家有兴趣可以参考官方文档继续研究下。

GET /_search
{
    "query": {
        "function_score": {
          "functions": [
            {
              "gauss": {
                "price": {
                  "origin": "0",
                  "scale": "20"
                }
              }
            },
            {
              "gauss": {
                "location": {
                  "origin": "11, 12",
                  "scale": "2km"
                }
              }
            }
          ],
          "query": {
            "match": {
              "properties": "balcony"
            }
          },
          "score_mode": "multiply"
        }
    }
}

四、合并得分


GET /_search
{
    "query": {
        "function_score": {
          "query": { "match_all": {} },
          "boost": "5", 
          "functions": [
              {
                  "filter": { "match": { "test": "bar" } },
                  "random_score": {}, 
                  "weight": 23
              },
              {
                  "filter": { "match": { "test": "cat" } },
                  "weight": 42
              }
          ],
          "max_boost": 42,
          "score_mode": "max",
          "boost_mode": "multiply",
          "min_score" : 42
        }
    }
}


参数说明:


max_boost

可以通过设置 max_boost 参数将新分数限制为不超过某个限制。 max_boost 的默认值是 FLT_MAX。


min_score

默认情况下,修改分数不会更改匹配的文档。 要排除不满足某个分数阈值的文档,可以将 min_score 参数设置为所需的分数阈值。


参数 score_mode 指定如何组合计算的分数:


multiply 相乘 (default)


sum 求和


avg 平均分


first 使用具有匹配过滤器的第一个函数的得分


max 使用最高分


min 使用最低分


boost_mode定义新计算的分数与查询的分数相结合。 具体选项:


multiply 查询得分和函数得分相乘,默认


replace 仅使用函数得分,查询得分被忽略


sum 查询得分和函数得分求和


avg 查询得分和函数得分取平均值


max 取查询得分和函数得分的最大值


min 取查询得分和函数得分的最小值


总结


本文主要介绍了ES中自定义评分函数function_score的使用场景以及各种评分函数的用法。

目录
相关文章
|
2月前
|
C++ 容器
函数对象包装器function和bind机制
函数对象包装器function和bind机制
22 0
|
4月前
|
SQL JavaScript 前端开发
【Azure 应用服务】Azure JS Function 异步方法中执行SQL查询后,Callback函数中日志无法输出问题
【Azure 应用服务】Azure JS Function 异步方法中执行SQL查询后,Callback函数中日志无法输出问题
|
7月前
|
SQL 人工智能 JSON
【AI大模型应用开发】2.2 Function Calling连接外部世界 - 【实战】查询数据库
【AI大模型应用开发】2.2 Function Calling连接外部世界 - 【实战】查询数据库
175 0
|
机器学习/深度学习 存储 人工智能
大语言模型的预训练[5]:语境学习、上下文学习In-Context Learning:精调LLM、Prompt设计和打分函数(Scoring Function)设计以及ICL底层机制等原理详解
大语言模型的预训练[5]:语境学习、上下文学习In-Context Learning:精调LLM、Prompt设计和打分函数(Scoring Function)设计以及ICL底层机制等原理详解
大语言模型的预训练[5]:语境学习、上下文学习In-Context Learning:精调LLM、Prompt设计和打分函数(Scoring Function)设计以及ICL底层机制等原理详解
|
存储
SAP端用于查询某采购组下某供应商待检物料数目的Function
本文的内容虽然用来描述SAP中采购相关的内容但是由于业余,所以很业余。待检,不清楚是不是SAP中的一个专业术语,反正我们公司的工厂的采购入库,会用到这个概念。你们公司如果拥有一个工厂进行制造,那么很可能会从其他公司采购一些零件,运到你们公司的工厂里进行加工或者组装。
2601 0
|
搜索推荐 Java API
Spring Boot 整合 Elasticsearch,实现 function score query 权重分查询
运行环境:JDK 7 或 8,Maven 3.0+技术栈:SpringBoot 1.5+,ElasticSearch 2.3.2 本文提纲一、ES 的使用场景二、运行 springboot-elasticsearch 工程三、springboot-elasticsearch 工程代码详解 一、ES 的使用场景 简单说,ElasticSearch(简称 ES)是搜索引擎,是结构化数据的分布式搜索引擎。
3389 0
|
搜索推荐 Java API
Spring Boot 整合 Elasticsearch,实现 function score query 权重分查询
摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载,保留摘要,谢谢! 『 预见未来最好的方式就是亲手创造未来 - 《史蒂夫·乔布斯传》 』 运行环境:JDK 7 或 8,Maven 3.
8084 0
|
JavaScript API 定位技术
百度地图API详解之事件机制,function“闭包”解决for循环和监听器冲突的问题:
原文: 百度地图API详解之事件机制,function“闭包”解决for循环和监听器冲突的问题:   百度地图API详解之事件机制 2011年07月26日 星期二 下午 04:06 和DOM编程里的事件模型一样,百度地图API也提供了类似的事件机制。
1533 0
|
1月前
|
中间件 Docker Python
【Azure Function】FTP上传了Python Function文件后,无法在门户页面加载函数的问题
通过FTP上传Python Function至Azure云后,出现函数列表无法加载的问题。经排查,发现是由于`requirements.txt`中的依赖包未被正确安装。解决方法为:在本地安装依赖包到`.python_packages/lib/site-packages`目录,再将该目录内容上传至云上的`wwwroot`目录,并重启应用。最终成功加载函数列表。
|
2月前
|
JavaScript
箭头函数与普通函数(function)的区别
箭头函数是ES6引入的新特性,与传统函数相比,它有更简洁的语法,且没有自己的this、arguments、super或new.target绑定,而是继承自外层作用域。箭头函数不适用于构造函数,不能使用new关键字调用。

热门文章

最新文章

下一篇
DataWorks