跨域查询(Cross-fields Queries)
为了阐述以字段为中心和以词条为中心的查询的区别,看看以字段为中心的most_fields查询的解释(译注:通过validate-query API得到):
// SENSE: 110_Multi_Field_Search/50_Cross_field.json
<1> operator设为了and,表示所有的词条都需要出现。
对于一份匹配的文档,peter和smith两个词条都需要出现在相同的字段中,要么是first_name字段,要么是last_name字段:
(+last_name:peter +last_name:smith)
而以词条为中心的方法则使用了下面这种逻辑:
cross_fields类型首先会解析查询字符串来得到一个词条列表,然后在任一字段中搜索每个词条。仅这个区别就能够解决在以字段为中心的查询中提到的3个问题中的2个,只剩下倒排文档频度的不同这一问题。
幸运的是,cross_fields类型也解决了这个问题,从下面的validate-query请求中可以看到:
GET /_validate/query?explain
{
"multi_match": {
"query": "peter smith",
"operator": "and",
"fields": [ "first_name", "last_name" ]
}
}
// SENSE: 110_Multi_Field_Search/50_Cross_field.json
<1> cross_fields
使用以词条为中心(Term-centric)进行匹配。
它通过混合(Blending)字段的倒排文档频度来解决词条频度的问题:
如果你包含了使用不同解析链(Analysis Chain)的字段,它们会以和best_fields相同的方式被添加到查询中。比如,如果我们将title字段添加到之前的查询中(假设它使用了一个不同的解析器),得到的解释如下所示:
(
+blended("peter", fields: [first_name, last_name])
)
当使用了minimum_should_match以及operator参数时,这一点尤为重要。
逐字段加权(Per-field Boosting)
使用cross_fields查询相比使用自定义_all字段的一个优点是你能够在查询期间对个别字段进行加权。
对于first_name和last_name这类拥有近似值的字段,也许加权是不必要的,但是如果你通过title和description字段来搜索书籍,那么你或许会给予title字段更多的权重。这可以通过前面介绍的caret(^)语法来完成:
能够对个别字段进行加权带来的优势应该和对多个字段执行查询伴随的代价进行权衡,因为如果使用自定义的_all字段,那么只需要要对一个字段进行查询。选择能够给你带来最大收益的方案。