两个Elaticsearch查询问题分析

2022-01-18 10:28:58 浏览数 (1)

这次给大家分享两个Es查询问题的实际案例,分别跟文本匹配和统计查询有关,直接进入正题。

看上去不相关,实际上却很合理的文本匹配问题

一大早A君找到我问了个问题:问什么搜一个手机号"15858593403",排在第一位的却是个看上去一点关系都没有的结果呢,符合预期的结果却排在第二位?

结果如图,确实一个不相关的手机号结果出现在了第一位,而且匹配分真的要高于符合预期的第二个结果,那为什么会出现这种情况呢?

从查询结果可以看到匹配分_score不是比较"规整"的数字,可以推测应该是个match匹配结果,翻看下对应的请求(只摘要展示核心部分):

的确如此,先复习下match和match_phrase查询条件:这两个条件第一步都会对查询词进行分词,match直接检索倒排索引取各词元的id_set交集,而match_phrase还需要计算词元间的position_gap来判断字符顺序是否符合查询词的顺序。

显而易见,mobile条件要求的字符顺序在第一个结果中并不符合,那么问题大概率出现在name字段上,可以看到查询要求的是分词结果在13个词元范围内则要求必须满足13个词元全部满足,多于13个词元要求90%的匹配度。

这里插播下minimum_should_match参数,match条件其实类似于bool查询,默认是把分词后的每个词元都当作should条件中的一个clause,这样minimum_should_match参数表面上的匹配度实际上就转换成分词后需要匹配的clause个数(词元格式),具体的转换方式大概是max(1, floor(minimum_should_match * num_of_clauses))。

好了,这个时候就必须看下name这个字段的分词器了:

是个单字分词,也就是18688034559分词后为[1,8,6,8,8,0,3,4,5,5,9],去重后得到[0,1,3,4,5,6,8,9],而查询词15858593403分词后为[1,5,8,5,8,5,9,3,4,0,3],去重后得到[0,1,3,4,5,8,9],手机号为11位,在13词范围内,所以必须要全部词元匹配,显然上面的分词结果符合要求。

分析到这里就真相大白了,尽管看上去丝毫不相关,但是搜索引擎很耿直的执行了我们的查询并给出了很合理的结果,这也是实际搜索应用中很容易遇到的文本匹配问题,希望大家能够好好体会。

嗯。。案例中的手机号都是处理后的伪号码。


看上去不合理,实际上很科学的统计查询问题

还是A君问了问题,为什么明明有两条yyyy_id相同的记录,但是在统计查询中却出不来呢?

直接翻查询请求:

可以看到是一个比较简单的terms统计查询,大意是查询xxxx_id为8并且yyyy_id>0的记录,将查询结果按yyyy_id聚合(group by),并且按照聚合结果倒序展示。

照道理,如果有yyyy_id相同的两条记录,那么肯定会展示在统计结果的前面,但是实际操作中并没有在统计结果中看到预期的yyyy_id相同的记录,而是需要缩小range条件中yyyy_id的gt范围(gt:0 => gt:1224545)才能够看到预期的结果,这又是什么诡异的姿势?

首先来了解下terms统计的一些"潜规则",terms统计默认是从索引中取top10(size=10)的数据,当然可以通过设置size参数来扩大topN的范围(这里也推荐这么做,可以让其他人在看到查询的时候就了解清楚背景,避免掉坑)。

即使如此,两条相同yyyy_id的记录聚合值为2也应该进入top10才对,那么这里就到第二个需要注意的地方,这个test_10索引是有10个shard的,terms统计默认的top10是并行在各shard中分别统计各shard的top10,然后汇总所有shard的统计结果再得到最终的top10结果,可能这里大家有点绕晕了,简单画个图:

假设索引有3个分片,进行一个top5统计,目的是找出值相同的记录(大多数记录值都是唯一的),如果碰巧相同值的记录分散在不同的shard且排序靠后,那么很可能连单shard的top5都进不去,最终结果中看不到预期的L值也很自然了。之所以修改gt条件可以将预期结果召回,主要也是因为数据桶范围缩小,使得L值有机会进去shard的top5而已。

这个操作其实在Elasticsearch的官方文档上都有写,认真看过文档的同学应该对这个都有印象,terms统计的结果不保证100%精确,如果terms统计设置的size小于数据桶中的唯一值数量,那么就有可能会丢失部分统计结果,希望大家使用terms统计过程中要多多注意。

最后,答应的automaton又跳票了。。感觉还不能很好的用自己的语言讲解出来,尽量下一篇放出来,谢谢大家。

0 人点赞