Elasticsearch 按照标签匹配个数优先排序查询
有一种相似度匹配需求,需要以匹配到的标签个数优先,这种情况就需要用到自定义查询语句。
先上代码,这里我用的是PHP的数组结构,最终提交的时候是会转成json格式的,暂且不表:
'query' => [
'script_score' => [
"query" => [],
'script' => [
'source' => '
def matches = 0;
for (t in params.tags) {
if(doc["tags"].contains(t)) {
matches += 1;
}
}
return _score * matches * matches;
',
"params" => [
"tags" => $tags,
],
]
],
]
首先最外层的数组就是我们通常写的query
语句,放在body
中进行请求的,主要看query
里面的结构,这种需要自定义脚本处理评分的,query
中只放了一个script_score
:
script_score
包含了两个部分,一部分是query
,另外一部分是自定义的script
,这里面的query
,就是正常原本写在外层的query
中的查询结构,原本怎么写还是怎么写,比如这里面可能还会需要一个标签匹配的,那么继续加一个terms
来查询。
然后来看script
部分,这里面又分为两个东西:
- source 自定义的评分排序脚本
- params 自定义的评分脚本参数
首先看params
,这里我传递了$tags
,这是一个标签数组,最终会在source
里进行调用,source
部分会放到elasticsearch
中进行编译,形成类似于函数的东西,然后params
就是一个参数,在source
的代码中需要调用tags
这个参数,采用params.tags
来进行调用。
然后再看source
代码部分,这里面会把搜索到的结果doc
中的tags
字段(这doc中的tags
也是一个数组)与所期望的tags
进行校验对比,最后得到实际匹配的个数:matches
。
最后看source
中的return部分,这里会返回评分结果,这里的_score
是搜索本身计算的相似度评分,然后这个地方_score * matches * matches
,这里是采用标签个数对评分结果进行放大,标签数匹配越多,自然放大结果就越大。
举个例子:
匹配文档 | _score | 标签个数 | 结果分 | 排序位置 |
---|---|---|---|---|
文档A | 40 | 2 | 160 | 2 |
文档B | 30 | 3 | 270 | 1 |
可见最终受到标签影响更大,实现了标签结果数优先的排序。
当然,至于放大形式,比如说,评分一样,以标签数优先,那么不用进行标签平方
处理,另外所期望的放大结果根据具体情况可以自行处理。
另外,在文章末尾帖上elasticsearch
的脚本语法链接:
Kumfo 的杂货铺
php实现只需要一个QQ号就可以获得用户信息
TANKING赞 27阅读 7.3k评论 5
终于卷完了!Redis 打怪升级进阶成神之路(2023 最新版)!
民工哥赞 13阅读 1.1k
花了几个月时间把 MySQL 重新巩固了一遍,梳理了一篇几万字 “超硬核” 的保姆式学习教程!(持续更新中~)
民工哥赞 14阅读 2k
算法可视化:一文弄懂 10 大排序算法
破晓L赞 8阅读 969
硬卷完了!MongoDB 打怪升级进阶成神之路( 2023 最新版 )!
民工哥赞 7阅读 614
「刷起来」Go必看的进阶面试题详解
王中阳Go赞 4阅读 1.9k评论 1
架构设计-高性能篇
架构狂人赞 4阅读 811
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。