以字段为中心的查询(Field-centric Queries)

    问题1:在多个字段中匹配相同的单词

    考虑一下most_fields查询是如何执行的:ES会为每个字段生成一个match查询,然后将它们包含在一个bool查询中。

    我们可以将查询传入到validate-query API中进行查看:

    // SENSE: 110_Multi_Field_Search/40_Entity_search_problems.json

    它会产生下面的解释(explaination):

    1. (city:poland city:street city:w1v)
    2. (postcode:poland postcode:street postcode:w1v)

    你可以发现能够在两个字段中匹配poland的文档会比在一个字段中匹配了poland和street的文档的分值要高。

    问题2:减少长尾

    // SENSE: 110_Multi_Field_Search/40_Entity_search_problems.json

    <1> 所有的term必须存在。

    但是,使用best_fields或者most_fields,这些参数会被传递到生成的match查询中。该查询的解释如下(译注:通过validate-query API):

    1. (+city:poland +city:street +city:w1v)
    2. (+country:poland +country:street +country:w1v)
    3. (+postcode:poland +postcode:street +postcode:w1v)

    换言之,使用and操作符时,所有的单词都需要出现在相同的字段中,这显然是错的!这样做可能不会有任何匹配的文档。

    问题3:词条频度

    在一节中,我们解释了默认用来计算每个词条的相关度分值的相似度算法TF/IDF:

    • 词条频度(Term Frequency)::

    在一份文档中,一个词条在一个字段中出现的越频繁,文档的相关度就越高。

    考虑使用first_name和last_name字段搜索”Peter Smith”的例子。Peter是一个常见的名字,Smith是一个常见的姓氏 - 它们的IDF都较低。但是如果在索引中有另外一个名为Smith Williams的人呢?Smith作为名字是非常罕见的,因此它的IDF值会很高!

    像下面这样的一个简单查询会将Smith Williams放在Peter Smith前面(译注:含有Smith Williams的文档分值比含有Peter Smith的文档分值高),尽管Peter Smith明显是更好的匹配:

    // SENSE: 110_Multi_Field_Search/40_Bad_frequencies.json

    smith在first_name字段中的高IDF值会压倒peter在first_name字段和smith在last_name字段中的两个低IDF值。

    解决方案

    这个问题仅在我们处理多字段时存在。如果我们将所有这些字段合并到一个字段中,该问题就不复存在了。我们可以向person文档中添加一个full_name字段来实现:

    1. "first_name": "Peter",
    2. "last_name": "Smith",
    3. "full_name": "Peter Smith"

    当我们只查询full_name字段时:

    • 拥有更多匹配单词的文档会胜过那些重复出现一个单词的文档。
    • first_name和last_name的倒排文档频度会被合并,因此smith无论是first_name还是last_name都不再重要。
      尽管这种方法能工作,可是我们并不想存储冗余数据。因此,ES为我们提供了两个解决方案 - 一个在索引期间,一个在搜索期间。下一节对它们进行讨论。