ElasticStack学习(十):深入ElasticSearch搜索之QueryFiltering、多/单字符串的多字段查询
一、复合查询
1、在elasticsearch中,有query和filter两种不同的context。query context进行了相关性算分,filter context不需要进行算分,同时可以利用cache,获取更好的性能。
2、bool query:一个布尔查询,是一个或者多个查询子句的组合,总共有四种类型的子句,其中2种影响算分,2种不影响算分。
布尔查询也涉及相关性算分,因为匹配的子句越多,相关性算分越高。对于布尔查询中的每个查询子句计算得出的算分会被合并到总的相关性算分中。
子查询可以任意顺序出现,同时可以嵌套多个子查询。
布尔查询的算分过程:
1)查询should语句中的查询;
2)对查询结果的评分进行求和;
3)乘以匹配语句的总数;
4)除以所有语句的总数;
3、复合查询应用
1)must_not与filter
2)should
3)bool嵌套
4)对于should下同一层级的竞争字段,具有相同的权重,若通过嵌套bool查询,可以改变对算分的影响。
5)控制字段boost权重,来影响查询返回的结果。
6)要求满足相关度高的文档在前或者排除不相关条件的文档,boosting query提升了precision,同时也提升了recall。
二、单字符串多字段查询
1)背景示例展示:
从示例中可以看出,对title和body两个字段进行“brown fox”的匹配,由于第二条只有在body中有brown fox,而第一条在title,body中均有匹配。所以,第一条的综合算分比第二条的算分要高。
2)disjunction max query
对于上例中title与body相互竞争,在查询brown fox时,更应该将第二条信息搜索出来。因此,对于搜索策略不应该将分数简单相加,而是应该找到最佳匹配的字段评分。
disjunction max query可以按最匹配字段评分进行返回。
从上图可以看出,通过disjunction max query进行查询,获取了最合适的匹配结果。
3)tie breaker
通过对quice pets进行查询,会发现两条文档的评分是一样的,这是因为quick pets做为查询term存在,在title或body中存在,两者的评分是一样的。为了获取最佳匹配,可以使用tie breaker。如下图所示:
可以看出,文档2排在了文档1的前面,原因是文档2的title和body,分别存有quick或pets,而文档1中只有title存在有一个quick。因此文档2的评分比文档1的高。
tie breaker的作用:tie breaker是一个介于0-1之间的浮点数,1代表使用最佳匹配;0代表所有语句同等重要。
获得最佳匹配语句的评分;
将其他匹配语句的评分与tie breaker相乘;
对以上评分求和并规范化;
4)multi match
当输入单个字符串进行查询时,通常会遇到三种情形:
a)最佳字段
当字段之间相互竞争,又相互关联时,评分来自于最匹配字段,比如上述的title和body字段。如当搜索“brown fox”时,此时该词组比两个独立的单词更有意义,因此文档在相同字段中包含的词最多越好,评分也来自于最匹配字段。
b)多数字段
为了对相关度进行微调,常用的技术就是将相同的数据索引到不同的字段,以匹配更多的文档。具体操作就是:
在主字段抽取词干,加入同义词、变音词、口语词,以匹配更多的字段;
相同的文本,加入子字段,以提供更加精确的匹配;
其他字段作为匹配文档提高相关度的信号,匹配字段最多越好;
通过上图可以发现,文档2更符合quicking brown的搜索条件,但是它排在了第2位,原因就是两个字段采用了英文分词器,而查询的实际上是quick、brown两个term,在两个文档中的title或body字段中,存在于这两个词。又因为第一个文档的相应字段总词数比第二个文档的相应字段总词数少,所以文档1评分会较高。
对上图分析发现,用广度匹配字段body,以包括尽可能多的文档,提升了召回率,同时对body字段增加了子字段,将std作为信号将相关度更高的文档置于结果顶部。
每个字段对于最终评分的贡献可以通过自定义值boost来控制。如下图所示:
未设置boost值的情况
将body设置boost的情况
c)混合字段
对于某些实体,例如人名、地址、图书信息。需要在多个字段中确定信息,单个字段只能作为整体的一部分。希望在列出的字段中找到尽可能多的词。
比如对于街道+门牌号存在于指定搜索字段的文档记录,如果想用most_fileds进行搜索是无法直接进行搜索的,对于operator=and也不能使用,因为它不适用于跨字段场景中。
而之前用于字段中的copy_to,虽然可以解决此类问题,但是需要额外的存储空间,因此也不是最优的解决方式。
从上图中可以看出,cross_fields可以配合operator=and进行跨字段的查询匹配,同时与copy_to相比,它还可以在搜索时为单个字段提升权重,如下图所示:
大家可关注我的公众号
知识学习来源:阮一鸣:《elasticsearch核心技术与实战》