松哥原创的 Spring Boot 视频教程已经杀青,感兴趣的小伙伴戳这里-->松哥要升级 SpringBoot 视频了,看看新增了哪些内容!
ElasticSearch 系列已经整到第 22 篇啦,今天我们来学习 Es 中的复合查询,前面已经和大家分享过一次复合查询了,今天我们来看看复合查询中的 function_score query 和 boosting query。
如果大家觉得视频风格还能接受,也可以看看松哥的付费视频:Spring Boot+Vue+微人事视频教程
以下是视频笔记:
注意,笔记只是视频内容的一个简要记录,因此笔记内容比较简单,完整的内容可以查看视频。
17.4 function_score query
场景:例如想要搜索附近的肯德基,搜索的关键字是肯德基,但是我希望能够将评分较高的肯德基优先展示出来。但是默认的评分策略是没有办法考虑到餐厅评分的,他只是考虑相关性,这个时候可以通过 function_score query 来实现。
准备两条测试数据:
PUT blog
{
"mappings": {
"properties": {
"title":{
"type": "text",
"analyzer": "ik_max_word"
},
"votes":{
"type": "integer"
}
}
}
}
PUT blog/_doc/1
{
"title":"Java集合详解",
"votes":100
}
PUT blog/_doc/2
{
"title":"Java多线程详解,Java锁详解",
"votes":10
}
现在搜索标题中包含 java 关键字的文档:
GET blog/_search
{
"query": {
"match": {
"title": "java"
}
}
}
查询结果如下:
默认情况下,id 为 2 的记录得分较高,因为他的 title 中包含两个 java。
如果我们在查询中,希望能够充分考虑 votes 字段,将 votes 较高的文档优先展示,就可以通过 function_score 来实现。
具体的思路,就是在旧的得分基础上,根据 votes 的数值进行综合运算,重新得出一个新的评分。
具体有几种不同的计算方式:
-
weight
-
random_score
-
script_score
-
field_value_factor
weight
weight 可以对评分设置权重,就是在旧的评分基础上乘以 weight,他其实无法解决我们上面所说的问题。具体用法如下:
GET blog/_search
{
"query": {
"function_score": {
"query": {
"match": {
"title": "java"
}
},
"functions": [
{
"weight": 10
}
]
}
}
}
查询结果如下:
可以看到,此时的评分,在之前的评分基础上*
10
random_score
random_score
会根据 uid 字段进行 hash 运算,生成分数,使用 random_score
时可以配置一个种子,如果不配置,默认使用当前时间。
GET blog/_search
{
"query": {
"function_score": {
"query": {
"match": {
"title": "java"
}
},
"functions": [
{
"random_score": {}
}
]
}
}
}
script_score
自定义评分脚本。假设每个文档的最终得分是旧的分数加上votes。查询方式如下:
GET blog/_search
{
"query": {
"function_score": {
"query": {
"match": {
"title": "java"
}
},
"functions": [
{
"script_score": {
"script": {
"lang": "painless",
"source": "_score + doc['votes'].value"
}
}
}
]
}
}
}
现在,最终得分是 (oldScore+votes)*oldScore
。
如果不想乘以 oldScore,查询方式如下:
GET blog/_search
{
"query": {
"function_score": {
"query": {
"match": {
"title": "java"
}
},
"functions": [
{
"script_score": {
"script": {
"lang": "painless",
"source": "_score + doc['votes'].value"
}
}
}
],
"boost_mode": "replace"
}
}
}
通过 boost_mode
参数,可以设置最终的计算方式。该参数还有其他取值:
-
multiply:分数相乘
-
sum:分数相加
-
avg:求平均数
-
max:最大分
-
min:最小分
-
replace:不进行二次计算
field_value_factor
这个的功能类似于 script_score
,但是不用自己写脚本。
假设每个文档的最终得分是旧的分数乘以votes。查询方式如下:
GET blog/_search
{
"query": {
"function_score": {
"query": {
"match": {
"title": "java"
}
},
"functions": [
{
"field_value_factor": {
"field": "votes"
}
}
]
}
}
}
默认的得分就是oldScore*votes
。
还可以利用 es 内置的函数进行一些更复杂的运算:
GET blog/_search
{
"query": {
"function_score": {
"query": {
"match": {
"title": "java"
}
},
"functions": [
{
"field_value_factor": {
"field": "votes",
"modifier": "sqrt"
}
}
],
"boost_mode": "replace"
}
}
}
此时,最终的得分是(sqrt(votes))。
modifier 中可以设置内置函数,其他的内置函数还有:
另外还有个参数 factor ,影响因子。字段值先乘以影响因子,然后再进行计算。以 sqrt 为例,计算方式为 sqrt(factor*votes)
:
GET blog/_search
{
"query": {
"function_score": {
"query": {
"match": {
"title": "java"
}
},
"functions": [
{
"field_value_factor": {
"field": "votes",
"modifier": "sqrt",
"factor": 10
}
}
],
"boost_mode": "replace"
}
}
}
还有一个参数 max_boost
,控制计算结果的范围:
GET blog/_search
{
"query": {
"function_score": {
"query": {
"match": {
"title": "java"
}
},
"functions": [
{
"field_value_factor": {
"field": "votes"
}
}
],
"boost_mode": "sum",
"max_boost": 100
}
}
}
max_boost
参数表示 functions 模块中,最终的计算结果上限。如果超过上限,就按照上线计算。
17.5 boosting query
boosting query 中包含三部分:
-
positive:得分不变
-
negative:降低得分
-
negative_boost:降低的权重
GET books/_search
{
"query": {
"boosting": {
"positive": {
"match": {
"name": "java"
}
},
"negative": {
"match": {
"name": "2008"
}
},
"negative_boost": 0.5
}
}
}
查询结果如下:
可以看到,id 为 86 的文档满足条件,因此它的最终得分在旧的分数上*0.5
。
ElasticSearch 系列其他文章:
-
打算出一个 ElasticSearch 教程,谁赞成,谁反对?
-
ElasticSearch 从安装开始
-
ElasticSearch 第三弹,核心概念介绍
-
ElasticSearch 中的中文分词器该怎么玩?
-
ElasticSearch 索引基本操作
-
ElasticSearch 文档的添加、获取以及更新
-
ElasticSearch 文档的删除和批量操作
-
ElasticSearch 文档路由,你的数据到底存在哪一个分片上?
-
ElasticSearch 并发的处理方式:锁和版本控制
-
ElasticSearch 中的倒排索引到底是什么?
-
ElasticSearch 动态映射与静态映射
-
ElasticSearch 四种字段类型详解
-
ElasticSearch 中的地理类型和特殊类型
-
ElasticSearch 23 种映射参数详解
-
ElasticSearch 如何配置某个字段的权重?
-
ElasticSearch 23 种映射参数详解【3】
-
ElasticSearch 映射模版
-
ElasticSearch 搜索入门
-
ElasticSearch 全文搜索怎么玩?
-
ElasticSearch 打错字还能搜索到?试试 fuzzy query!
-
ElasticSearch 复合查询,理解 Es 中的文档评分策略!
1
50+ 需求文档免费下载!
2
Spring Security 教程合集
3
接了两个私活,都是血汗钱
本文分享自微信公众号 - 江南一点雨(a_javaboy)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。