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标签个数结果分排序位置
文档A4021602
文档B3032701

可见最终受到标签影响更大,实现了标签结果数优先的排序。

当然,至于放大形式,比如说,评分一样,以标签数优先,那么不用进行标签平方处理,另外所期望的放大结果根据具体情况可以自行处理。

另外,在文章末尾帖上elasticsearch的脚本语法链接:

https://www.elastic.co/guide/...


Kumfo 的杂货铺
做一些经验总结和一些学习心得分享,主要围绕PHP。 现在正在学习机器学习,会增加一些机器学习的思考分享。
avatar
kumfo
SegmentFault 后端工程师

程序生存法则:

6.6k 声望
4.1k 粉丝
0 条评论
推荐阅读
程序猿必读-防范CSRF跨站请求伪造
CSRF(Cross-site request forgery,中文为跨站请求伪造)是一种利用网站可信用户的权限去执行未授权的命令的一种恶意攻击。通过伪装可信用户的请求来利用信任该用户的网站,这种攻击方式虽然不是很流行,但是却...

mylxsw22阅读 15.2k评论 12

一文搞懂秒杀系统,欢迎参与开源,提交PR,提高竞争力。早日上岸,升职加薪。
前言秒杀和高并发是面试的高频考点,也是我们做电商项目必知必会的场景。欢迎大家参与我们的开源项目,提交PR,提高竞争力。早日上岸,升职加薪。知识点详解秒杀系统架构图秒杀流程图秒杀系统设计这篇文章一万多...

王中阳Go35阅读 2.6k评论 1

封面图
一个HTTP请求的曲折经历
作为程序员的我们每天都在和网络请求打交道,而前端程序员接触的最多的就是HTTP请求。平时工作中,处理网络请求之类的操作是最多的了。但是一个请求从客户端发出到被服务端处理、再回送响应,再被客户端接收这一...

nero24阅读 5.1k评论 1

Nginx 一网打尽:动静分离、压缩、缓存、黑白名单、跨域、高可用、性能优化...
早期的业务都是基于单体节点部署,由于前期访问流量不大,因此单体结构也可满足需求,但随着业务增长,流量也越来越大,那么最终单台服务器受到的访问压力也会逐步增高。时间一长,单台服务器性能无法跟上业务增...

民工哥23阅读 1.1k

封面图
Golang 中 []byte 与 string 转换
string 类型和 []byte 类型是我们编程时最常使用到的数据结构。本文将探讨两者之间的转换方式,通过分析它们之间的内在联系来拨开迷雾。

机器铃砍菜刀24阅读 58.4k评论 2

最好用的 python 库合集
🎈 分词 - jieba优秀的中文分词库,依靠中文词库,利用词库确定汉子之间关联的概率,形成分词结果 {代码...} 🎈 词云库 - wordcloud对数据中出现频率较高的 关键词 生成的一幅图像,予以视觉上的突出 {代码...} 🎈 ...

tiny极客11阅读 2.9k评论 2

封面图
计算机网络连环炮40问
本文已经收录到Github仓库,该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点,欢迎star~

程序员大彬14阅读 1.9k

avatar
kumfo
SegmentFault 后端工程师

程序生存法则:

6.6k 声望
4.1k 粉丝
宣传栏