当前位置:首页>编程日记>正文

【相关性搜索】 多字段搜索的两种方式——词中心与字段中心

背景

  • 首先看个例子,有两个 doc,一条是 albino elephant,一条是 elephant elephant
PUT test_elephant/_doc/1
{"title_text":"elephant","body_text":"elephant"
}PUT test_elephant/_doc/2
{"title_text":"albino","body_text":"elephant"
}
复制代码
  • 用户想查 albino elephant , 于是我们就这样写了一条 query 语句,期望可以召回 doc 2
GET test_elephant/_search
{"query": {"query_string": {"fields": ["title_text","body_text"],"query": "albino elephant"}}
}
复制代码
  • 但是实际结果却和我们预期的不一样,两个 doc 评分一模一样,那么这是为什么呢?

  • 首先 expalin 一下可以看到
doc1 max(title_text:elephant,body_text:elephant)
doc2 max(title_text:albino,body_text:elephant)
复制代码
  • 而因为 elephant 和 albino 在 title 字段中都出现了一次,所以分数一样,都是0.69
  • 那么为什么呢?
    • 我们通过 _validate/query?rewrite=true 可以看到这个 query 被翻译成

以字段为中心(field-centric) VS 以词为中心(term-centric)

  • 上述的那个例子就是以字段为中心中经典的『白化象问题』,那么到底什么是以字段为中心,什么是以词为中心呢?下图

  • 左边是为 以字段为中心,可见,字段为中心为query 在各个字段分别算分,然后按一定 function 求最终结果,也就是其实最终的结果也是整个 query 在哪个字段中表现最好。
    • 这种适用于用户意图只会命中一个字段时适用
    • 优势:符合结构化语义,易于控制不同字段权重
    • 问题:
      • 白化象问题(albino elephant) — 有更多搜索词匹配的文档没有被排在靠前的位置
      • 信号冲突(signal discordance) — 多字段 idf 不一,排序难被用户理解。比如一个人经常做演员很少做导演,然后搜索的时候,导演字段的分数就会非常高,造成当导演的电影排序靠前,造成用户困扰
  • 右边为 以词为中心,以词为中心则是词在不同字段中的分数,通过一定 function 算出(图中为 max),然后再将各个词的分数以一定 function 结合作为总分。
    • 这种实际上就是用户并不关系匹配的是什么字段,不关心文档结构,关心的只是匹配到了哪些词。
    • 优势:更符合用户心智,用户往往难以了解数据的结构
    • 问题:不好控制不同字段权重,实现复杂

ES 中的多字段检索方式

查看真实检索语句

  • 利用 _validate/query?rewrite=true 可以看到真实传个 lucene 的语句,便可看出其真实逻辑。也可用explain=true可以看见部分中间过程,但是效果没有 rewrite 直观

常用多字段检索

  • 下面利用 validate 对 title(keyword 字段) , title_text(ik 分词器) 和 body_text(ik 分词器) 进行查询,查询内容为 ZSearch 通用搜索
  • MultiMatch
    • best_fields - 字段中心,字段间 max ,可用 tie_breaker 调整字段间关系
      • (title:ZSearch 通用搜索 | (title_text:zsearch title_text:通用 title_text:搜索) | (body_text:zsearch body_text:通用 body_text:搜索))
    • most_fields - 字段中心 字段间相加
      • title:ZSearch 通用搜索 (title_text:zsearch title_text:通用 title_text:搜索) (body_text:zsearch body_text:通用 body_text:搜索)
    • cross_fields - 词中心 词在不同字段间取 max,然后相加
      • (((title_text:zsearch | body_text:zsearch) (title_text:通用 | body_text:通用) (title_text:搜索 | body_text:搜索)) | title:ZSearch 通用搜索)
  • QueryString - 字段中心 同 best_fields
    • (title:ZSearch 通用搜索 | (title_text:zsearch title_text:通用 title_text:搜索) | (body_text:zsearch body_text:通用 body_text:搜索))
  • SimpleQueryString 词中心,但词在不同字段间为相加
    • (title_text:zsearch title:ZSearch body_text:zsearch) ((title_text:通用 title_text:搜索) title:通用搜索 (body_text:通用 body_text:搜索))
  • 需要注意的是词为中心的查询方式均会受分词器影响,其中 simple query string 和 cross 采取了两种不同的实现方式
    • simple query string 为简单按空格分割,然后直接丢入各字段进行查询,因此是分词前的以词为中心,而不是最终的,及时设置了 analyzer 也依旧如此
    • cross_field 则是采取首先按分词器进行分组,同样的分词器内以词为中心在多字段进行查询,不同的分词器直接按字段取 max
  • 另外,多字段查询的minimum_should_match也只与一级子句(最外边的括号内的)有关,内部再分词均不会作用

扩展阅读

如何实现字段中心和词中心相结合

  1. 相似字段,按用户意图将字段分组,比如 姓 和 名 两个字段合并 姓名 一个字段,将不同意图的搜索完全分开
  2. 以词为中心进行兜底,以字段为中心进行加成,如下

多字段算分在信息检索领域的尝试

  • 传统BM25在计算相关性时把文档当做总体来考虑,但随着搜索技术的发展。文档慢慢的被结构化数据所取代。每个文档都会被切分成多个独立的域,尤其是垂直化的搜索。比如网页有可能被切分成标题,内容,主题词等域,这些域对文章主题的贡献不能同等对待,所以权重就要有所偏重。
  • BM25没有考虑这点。所以BM25F在此基础上做了一些改进,就是不再单单的将单词作为个体考虑,并且将文档也依照field划分为个体考虑,所以BM25F是每一个单词在各个field中分值的加权求和。

参考资料

  • Doug Turnbull,John Berryman 《相关性搜索-利用Solr与Elasticsearch创建智能应用》P120-192
  • Elasticsearch 权威指南
  • Elasticsearch 文档

http://www.coolblog.cn/news/1b63b7f431441d62.html

相关文章:

  • asp多表查询并显示_SpringBoot系列(五):SpringBoot整合Mybatis实现多表关联查询
  • s7day2学习记录
  • 【求锤得锤的故事】Redis锁从面试连环炮聊到神仙打架。
  • 矿Spring入门Demo
  • 拼音怎么写_老师:不会写的字用圈代替,看到孩子试卷,网友:人才
  • Linux 实时流量监测(iptraf中文图解)
  • Win10 + Python + GPU版MXNet + VS2015 + RTools + R配置
  • 美颜
  • shell访问php文件夹,Shell获取某目录下所有文件夹的名称
  • 如何优雅的实现 Spring Boot 接口参数加密解密?
  • LeCun亲授的深度学习入门课:从飞行器的发明到卷积神经网络
  • Mac原生Terminal快速登录ssh
  • java受保护的数据与_Javascript类定义语法,私有成员、受保护成员、静态成员等介绍...
  • mysql commit 机制_1024MySQL事物提交机制
  • 支撑微博千亿调用的轻量级RPC框架:Motan
  • jquery 使用小技巧
  • 2019-9
  • 法拉利虚拟学院2010 服务器,法拉利虚拟学院2010
  • vscode pylint 错误_将实际未错误的py库添加到pylint白名单
  • 科学计算工具NumPy(3):ndarray的元素处理
  • 工程师在工作电脑存 64G 不雅文件,被公司开除后索赔 41 万,结果…
  • linux批量创建用户和密码
  • newinsets用法java_Java XYPlot.setInsets方法代碼示例
  • js常用阻止冒泡事件
  • 气泡图在开源监控工具中的应用效果
  • 各类型土地利用图例_划重点!国土空间总体规划——土地利用
  • php 启动服务器监听
  • dubbo简单示例
  • 【设计模式】 模式PK:策略模式VS状态模式
  • [iptables]Redhat 7.2下使用iptables实现NAT
  • Ubuntu13.10:[3]如何开启SSH SERVER服务
  • CSS小技巧——CSS滚动条美化
  • JS实现-页面数据无限加载
  • 阿里巴巴分布式服务框架 Dubbo
  • 最新DOS大全
  • Django View(视图系统)
  • 阿里大鱼.net core 发送短信
  • 程序员入错行怎么办?
  • 两张超级大表join优化
  • 第九天函数
  • Linux软件安装-----apache安装
  • HDU 5988 最小费用流
  • Sorenson Capital:值得投资的 5 种 AI 技术
  • 《看透springmvc源码分析与实践》读书笔记一
  • 正式开课!如何学习相机模型与标定?(单目+双目+鱼眼+深度相机)
  • Arm芯片的新革命在缓缓上演
  • nagios自写插件—check_file
  • python3 错误 Max retries exceeded with url 解决方法
  • 行为模式之Template Method模式
  • 通过Spark进行ALS离线和Stream实时推荐