字段中心式查询 | Elasticsearch: 权威指南 | Elastic
2024-10-07
以上三个源于
most_fields
的问题都因为它是 字段中心式(field-centric) 而不是 词中心式(term-centric) 的:当真正感兴趣的是匹配词的时候,它为我们查找的是最匹配的 字段 。
首先查看这些问题存在的原因,再想如何解决它们。
回想一下 most_fields
查询是如何执行的:Elasticsearch 为每个字段生成独立的 match
查询,再用 bool
查询将他们包起来。
可以通过 validate-query
API 查看:
GET /_validate/query?explain { "query": { "multi_match": { "query": "Poland Street W1V", "type": "most_fields", "fields": [ "street", "city", "country", "postcode" ] } } }
生成 explanation
解释:
(street:poland street:street street:w1v) (city:poland city:street city:w1v) (country:poland country:street country:w1v) (postcode:poland postcode:street postcode:w1v)
可以发现, 两个 字段都与 poland
匹配的文档要比一个字段同时匹配 poland
与 street
文档的评分高。
在 匹配精度 中,我们讨论过使用 and
操作符或设置 minimum_should_match
参数来消除结果中几乎不相关的长尾,或许可以尝试以下方式:
{ "query": { "multi_match": { "query": "Poland Street W1V", "type": "most_fields", "operator": "and", "fields": [ "street", "city", "country", "postcode" ] } } }
但是对于 best_fields
或 most_fields
这些参数会在 match
查询生成时被传入,这个查询的 explanation
解释如下:
(+street:poland +street:street +street:w1v) (+city:poland +city:street +city:w1v) (+country:poland +country:street +country:w1v) (+postcode:poland +postcode:street +postcode:w1v)
换句话说,使用 and
操作符要求所有词都必须存在于 相同字段 ,这显然是不对的!可能就不存在能与这个查询匹配的文档。
在 什么是相关 中,我们解释过每个词默认使用 TF/IDF 相似度算法计算相关度评分:
想想用字段 first_name
和 last_name
查询 “Peter Smith” 的例子,
Peter 是个平常的名 Smith 也是平常的姓,这两者都具有较低的 IDF 值。但当索引中有另外一个人的名字是 “Smith Williams” 时, Smith 作为名来说很不平常,以致它有一个较高的 IDF 值!
下面这个简单的查询可能会在结果中将 “Smith Williams” 置于 “Peter Smith” 之上,尽管事实上是第二个人比第一个人更为匹配。
{ "query": { "multi_match": { "query": "Peter Smith", "type": "most_fields", "fields": [ "*_name" ] } } }
这里的问题是 smith
在名字段中具有高 IDF ,它会削弱 “Peter” 作为名和 “Smith” 作为姓时低 IDF 的所起作用。
存在这些问题仅仅是因为我们在处理着多个字段,如果将所有这些字段组合成单个字段,问题就会消失。可以为 person
文档添加 full_name
字段来解决这个问题:
{ "first_name": "Peter", "last_name": "Smith", "full_name": "Peter Smith" }
当查询 full_name
字段时:
minimum_should_match
和 operator
参数会像期望那样工作。
这么做当然是可行的,但我们并不太喜欢存储冗余数据。取而代之的是 Elasticsearch 可以提供两个解决方案——一个在索引时,而另一个是在搜索时——随后会讨论它们。
官方地址:https://www.elastic.co/guide/cn/elasticsearch/guide/current/field-centric.html