ElasticStack系列之十二 & 搜索结果研究
问题
使用 ElasticSearch 做搜索 时,比如用户输入 --> 柠檬,搜出来的结果 --> 柠檬汽水,柠檬味牙膏等在前面,真正想要的水果那个 柠檬 在后面。已经在中文分词中加了 柠檬,还是不管用,正常来说 tf、idf 都一样,影响排序的只有 field norms。按道理 “柠檬” 的 field length 最短,那么得分应该最高才对,为什么它没有排在第一位呢?
我这里补充一下:ElasticSearch5.x 以后使用的相关度算法为 BM25,但他仍然是一种相关性算法,只是对 TF/IDF 的改进。 用 BM25 还是 TF/IDF 和本问题的根源没有关系。
验证
为了验证这个结果,我实际测试了一下,过程如下:
创建一个空索引,使用 ik_max_word 分词器并写入 3 条数据
PUT testindex/
{
"mappings": {
"logs": {
"properties": {
"product": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
} PUT testindex/logs/
{"product":"柠檬"} PUT testindex/logs/
{"product":"柠檬汽水"} PUT testindex/logs/
{"product":"柠檬味牙膏"}
查询关键词"柠檬"
POST testindex/_search
{
"query": {
"match": {
"product": "柠檬"
}
}
}
查询结果:
"hits": {
"total": ,
"max_score": 0.85747814,
"hits": [
{
"_index": "testindex",
"_type": "logs",
"_id": "",
"_score": 0.85747814,
"_source": {
"product": "柠檬味牙膏"
}
},
{
"_index": "testindex",
"_type": "logs",
"_id": "",
"_score": 0.80226827,
"_source": {
"product": "柠檬汽水"
}
},
{
"_index": "testindex",
"_type": "logs",
"_id": "",
"_score": 0.7594807,
"_source": {
"product": "柠檬"
}
}
]
}
"柠檬" 居然真分数最低,非常出乎我的意料。于是,我在查询里打开 "explain":true 选项,查看分数是怎么计算的,发现 doc frequency, avgfieldlength 看着都不对。
问题解释
简而言之,ElasticSearch 的相关性打分计算是每个 shard 独立做的。一个索引默认 5 个shard,如果像示例里那样,写入的文档比较少,可能这些文档分布在不同的 shard,造成各个 shard 分别计算各自的得分的时候,并没有将这几条文档放在一起产生统计数据。 各自的打分不具有可比性。
所以,后面我又做了一个测试,删掉这个索引,重新创建一个,将 shard 设置为 1,重新写入同样 3 条文档后再搜索,"柠檬” 是排第一位返回的。
那么怎么看待这个问题?
因为 ElasticSearch 是分布式搜索系统,各个shard独立搜索,独立计算该shard上的文档打分,当数据量比较大的情况下,上面说的差异统计上看基本被抹平了,通常没什么问题。但如果索引的文档比较少,不同 shard 之间对同一个搜索关键词的统计数据差异可能就比较大,这种情况下只能使用一个 shard 来解决了。
故这里就可以解释我最初问题中所说的,通过 explain api 去查看打分的过程时,doc frequency 和 avgfieldlength 这类参与打分的统计值看起来“不正确”。之所为认为它“不正确”,是因为一开始没意识到,ES默认的打分是每个shard单独进行的,并非参考的全局统计数据。
建议
故在做实际搜索应用的时候,则需要根据应用所针对的领域范围,补充打分需要的其他参考信息来提高搜索准确率。 比如收集用户搜索的常用热词,为热词增加权重,或者为信息添加类别信息,为某些类别提高权重等等。
另外:
可以在搜索的时候增加参数:?search_type=dfs_query_then_fetch ,即先分别获得每个分片本地的 IDF ,然后根据结果再计算整个索引的全局 IDF,也是可以实现。不过这种方式代价比较高,适合测试的时候使用,生成环境下还是不建议使用的。
推荐可以看一篇 github 上的 issue
总结
ElasticSearch 这类搜索引擎主要提供 “搜的到” 的功能,而能否 “搜的准”,需要理解 ElasticSearch 能提供的打分机制,并结合领域信息,对信息做提炼或者补充,然后利用这些打分机制去调配,让搜索结果符合应用的需求。但搜的“准不准”,一千个人有一千个理解,做好不是一件容易的事。
BM25 和 基于tf-idf的向量空间模型,我觉得有本质的区别,前者是概率模型,后者是代数模型。
ElasticStack系列之十二 & 搜索结果研究的更多相关文章
- hbase源码系列(十二)Get、Scan在服务端是如何处理
hbase源码系列(十二)Get.Scan在服务端是如何处理? 继上一篇讲了Put和Delete之后,这一篇我们讲Get和Scan, 因为我发现这两个操作几乎是一样的过程,就像之前的Put和Del ...
- CRL快速开发框架系列教程十二(MongoDB支持)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- webpack4 系列教程(十二):处理第三方JavaScript库
教程所示图片使用的是 github 仓库图片,网速过慢的朋友请移步<webpack4 系列教程(十二):处理第三方 JavaScript 库>原文地址.或者来我的小站看更多内容:godbm ...
- OSGi 系列(十二)之 Http Service
OSGi 系列(十二)之 Http Service 1. 原始的 HttpService (1) 新建 web-osgi 工程,目录结构如下: (2) HomeServlet package com. ...
- ElasticStack系列之十六 & ElasticSearch5.x index/create 和 update 源码分析
开篇 在ElasticSearch 系列十四中提到的问题即 ElasticStack系列之十四 & ElasticSearch5.x bulk update 中重复 id 性能骤降,继续这个问 ...
- Java 设计模式系列(十二)策略模式(Strategy)
Java 设计模式系列(十二)策略模式(Strategy) 策略模式属于对象的行为模式.其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换.策略模式使得算法可以 ...
- Dubbo学习系列之十二(Quartz任务调度)
Quartz词义为"石英"水晶,然后聪明的人类利用它发明了石英手表,因石英晶体在受到电流影响时,它会产生规律的振动,于是,这种时间上的规律,也被应用到了软件界,来命名了一款任务调度 ...
- SQL注入之Sqli-labs系列第十二关
开始挑战第十二关(Error Based- Double quotes- String) 12点半了,不困,继续,继续,继续 先看看页面,通常的使用单引号等进行操作,看看啥么情况先 咦,出现错误信息了 ...
- SCM白色幼儿系列(十二) Proteus仿真软件简介
Proteus软件是英国Labcenter electronics公司出版的EDA工具软件.经常使用于单片机等数字电路仿真,分为ISIS和ARES两个程序,前者用于仿真,后者用于设计PCB.我们常使用 ...
随机推荐
- CF 1100C NN and the Optical Illusion(数学)
NN is an experienced internet user and that means he spends a lot of time on the social media. Once ...
- Beta发布文案+美工
团队名称:探路者 1蔺依铭:http://www.cnblogs.com/linym762/(组长) 2张恩聚:http://www.cnblogs.com/zej87/ 3米赫:http://www ...
- 提不起劲想赶紧完工 Scrum Meeting 博客汇总
提不起劲想赶紧完工 Scrum Meeting 博客汇总 一.Alpha阶段 1,第一次Scrum Meeting 2,第二次Scrum Meeting 3,第三次Scrum Meeting 4,第四 ...
- 找"1"
题目:给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的次数. 要求:1.写一个函数f(N),返回1到N之间出现“1”的个数.例如f(12)=5. 2.在32位整数范围内 ...
- java拓荒者
因为是初学者 最近在看那个<java从入门到精通 韩顺平>的视频 觉得好不错 虽然视频的分辨率强差人意 但仍可接受 学知识嘛 用我们广东话说 :“鬼叫你穷,顶硬上” 韩老师的声音较好 课堂 ...
- 第一次spring冲刺第5天
今天进行讨论基础功能的核心代码方面,还有简单的讨论继续关于界面的美化, 计算生成的答案功能 public class Core {// char[]h={'+','-','*','/'};int re ...
- jQuery 版本选择与常见插件库总结
在日常的开发中jQuery作为一个流行多年的轻量级 JavaScript 库,使用十分的普遍,主要源于它的便捷性和实用性非常高. 在此总结一些关于jQuery版本的区别和选择的建议,以及一些常见插件库 ...
- Linux上的free命令详解-收藏
解释一下Linux上free命令的输出. 下面是free的运行结果,一共有4行.为了方便说明,我加上了列号.这样可以把free的输出看成一个二维数组FO(Free Output).例如: FO[2][ ...
- Java 几种调度任务的Timer、ScheduledExecutor、 开源工具包 Quartz、开源工具包 JCronTab
关于Java中的调度问题,是比较常见的问题,一直没有系统的梳理,现在梳理一下 注意:Quartz的例子 需要在特定的版本上执行,不同的版本使用方法不同,但是总的来说方法大同小异.本例子的版本是1.8 ...
- 【译】关于vertical-align你应知道的一切
原文地址:Vertical-Align: All You Need To Know 通常我们需要垂直对齐并排的元素. CSS提供了一些可实现的方法:有时我用浮动float来解决,有时用position ...