[Elasticsearch] 多字段搜索 (一) - 多个及单个查询字符串 <译>

多字段搜索(Multifield Search)

本文翻译自官方指南的Multifield Search一章。

查询很少是只拥有一个match查询子句的查询。我们经常需要对一个或者多个字段使用相同或者不同的查询字符串进行搜索,这意味着我们需要将多个查询子句和它们得到的相关度分值以一种有意义的方式进行合并。

也许我们正在寻找一本名为战争与和平的书,它的作者是Leo Tolstoy。也许我们正在使用"最少应该匹配(Minimum Should Match)"来搜索ES中的文档。另外我们也可能会寻找拥有名为John而姓为Smith的用户。

在本章中我们会讨论一些构建多字段搜索的工具,以及如何根据你的实际情况来决定使用哪种方案。

多个查询字符串(Multiple Query Strings)

处理字段查询最简单的方法是将搜索词条对应到特定的字段上。如果我们知道战争与和平是标题,而Leo Tolstoy是作者,那么我们可以简单地将每个条件当做一个match子句,然后通过bool查询将它们合并:

GET /_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title":  "War and Peace" }},
        { "match": { "author": "Leo Tolstoy"   }}
      ]
    }
  }
}

bool查询采用了一种"匹配越多越好(More-matches-is-better)"的方法,因此每个match子句的分值会被累加来得到文档最终的_score。匹配两个子句的文档相比那些只匹配一个子句的文档的分值会高一些。

当然,你并不是只能使用match子句:bool查询可以包含任何其他类型的查询,包括其它的bool查询。我们可以添加一个子句来指定我们希望的译者:

GET /_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title":  "War and Peace" }},
        { "match": { "author": "Leo Tolstoy"   }},
        { "bool":  {
          "should": [
            { "match": { "translator": "Constance Garnett" }},
            { "match": { "translator": "Louise Maude"      }}
          ]
        }}
      ]
    }
  }
}

我们为什么将译者的查询子句放在一个单独的bool查询中?所有的4个match查询都是should子句,那么为何不将译者的查询子句和标题及作者的查询子句放在同一层次上呢?

答案在于分值是如何计算的。bool查询会运行每个match查询,将它们的分值相加,然后乘以匹配的查询子句的数量,最后除以所有查询子句的数量。相同层次的每个子句都拥有相同的权重。在上述查询中,bool查询中包含的译者查询子句只占了总分值的三分之一。如果我们将译者查询子句放到和标题及作者相同的层次上,就会减少标题和作者子句的权重,让它们各自只占四分之一。

设置子句优先级

上述查询中每个子句占有三分之一的权重也许并不是我们需要的。相比译者字段,我们可能对标题和作者字段更有兴趣。我们对查询进行调整来让标题和作者相对更重要。

在所有可用措施中,我们可以采用的最简单的方法是boost参数。为了增加titleauthor字段的权重,我们可以给它们一个大于1boost值:

GET /_search
{
  "query": {
    "bool": {
      "should": [
        { "match": {
            "title":  {
              "query": "War and Peace",
              "boost": 2
        }}},
        { "match": {
            "author":  {
              "query": "Leo Tolstoy",
              "boost": 2
        }}},
        { "bool":  {
            "should": [
              { "match": { "translator": "Constance Garnett" }},
              { "match": { "translator": "Louise Maude"      }}
            ]
        }}
      ]
    }
  }
}

以上的title和k字段的boost值为2。 嵌套的bool查询自居的默认boost值为k。

通过试错(Trial and Error)的方式可以确定"最佳"的boost值:设置一个boost值,执行测试查询,重复这个过程。一个合理boost值的范围在110之间,也可能是15。比它更高的值的影响不会起到很大的作用,因为分值会被规范化(Normalized)。

单一查询字符串(Single Query String)

bool查询是多字段查询的中流砥柱。在很多场合下它都能很好地工作,特别是当你能够将不同的查询字符串映射到不同的字段时。

问题在于,现在的用户期望能够在一个地方输入所有的搜索词条,然后应用能够知道如何为他们得到正确的结果。所以当我们把含有多个字段的搜索表单称为高级搜 索(Advanced Search)时,是有一些讽刺意味的。高级搜索虽然对用户而言会显得更"高级",但是实际上它的实现方式更简单。

对于多词,多字段查询并没有一种万能的方法。要得到最佳的结果,你需要了解你的数据以及如何使用恰当的工具。

了解你的数据

当用户的唯一输入就是一个查询字符串时,你会经常碰到以下三种情况:

最佳字段(Best fields)

当搜索代表某些概念的单词时,例如"brown fox",几个单词合在一起表达出来的意思比单独的单词更多。类似title和body的字段,尽管它们是相关联的,但是也是互相竞争着的。文档在相同的 字段中应该有尽可能多的单词(译注:搜索的目标单词),文档的分数应该来自拥有最佳匹配的字段。

多数字段(Most fields)

一个用来调优相关度的常用技术是将相同的数据索引到多个字段中,每个字段拥有自己的分析链(Analysis Chain)。

主要字段会含有单词的词干部分,同义词和消除了变音符号的单词。它用来尽可能多地匹配文档。

相同的文本可以被索引到其它的字段中来提供更加精确的匹配。一个字段或许会包含未被提取词干的单词,另一个字段是包含了变音符号的单词,第三个字段则使用shingle来提供关于单词邻近度(Word Proximity)的信息。

以上这些额外的字段扮演者signal的角色,用来增加每个匹配的文档的相关度分值。越多的字段被匹配则意味着文档的相关度越高。

跨字段(Cross fields)

对于一些实体,标识信息会在多个字段中出现,每个字段中只含有一部分信息:

  • Person:first_name 和 last_name
  • Book:titleauthor 和 description
  • Address:streetcitycountry 和 postcode

此时,我们希望在任意字段中找到尽可能多的单词。我们需要在多个字段中进行查询,就好像这些字段是一个字段那样。



以上这些都是多词,多字段查询,但是每种都需要使用不同的策略。我们会在本章剩下的部分解释每种策略。

from:http://blog.csdn.net/dm_vincent/article/details/41800351#t4

时间: 2024-10-23 17:01:32

[Elasticsearch] 多字段搜索 (一) - 多个及单个查询字符串 <译>的相关文章

[Elasticsearch] 多字段搜索 (一) - 多个及单个查询字符串

多字段搜索(Multifield Search) 本文翻译自官方指南的Multifield Search一章. 查询很少是只拥有一个match查询子句的查询.我们经常需要对一个或者多个字段使用相同或者不同的查询字符串进行搜索,这意味着我们需要将多个查询子句和它们得到的相关度分值以一种有意义的方式进行合并. 也许我们正在寻找一本名为战争与和平的书,它的作者是Leo Tolstoy.也许我们正在使用"最少应该匹配(Minimum Should Match)"来搜索ES中的文档.另外我们也可

[Elasticsearch] 多字段搜索 (六) - 自定义_all字段,跨域查询及精确值字段

自定义_all字段 在元数据:_all字段中,我们解释了特殊的_all字段会将其它所有字段中的值作为一个大字符串进行索引.尽管将所有字段的值作为一个字段进行索引并不是非常灵活.如果有一个自定义的_all字段用来索引人名,另外一个自定义的_all字段用来索引地址就更好了. ES通过字段映射中的copy_to参数向我们提供了这一功能: PUT /my_index { "mappings": { "person": { "properties": {

[Elasticsearch] 多字段搜索 (四) - 跨字段实体搜索

跨字段实体搜索(Cross-fields Entity Search) 现在让我们看看一个常见的模式:跨字段实体搜索.类似person,product或者address这样的实体,它们的信息会分散到多个字段中.我们或许有一个person实体被索引如下: { "firstname": "Peter", "lastname": "Smith" } 而address实体则是像下面这样: { "street": &

[Elasticsearch] 多字段搜索 (五) - 以字段为中心的查询

以字段为中心的查询(Field-centric Queries) 上述提到的三个问题都来源于most_fields是以字段为中心(Field-centric),而不是以词条为中心(Term-centric):它会查询最多匹配的字段(Most matching fields),而我们真正感兴趣的最匹配的词条(Most matching terms). NOTE best_fields同样是以字段为中心的,因此它也存在相似的问题. 首先我们来看看为什么存在这些问题,以及如何解决它们. 问题1:在多个

Elasticsearch 全字段搜索_all,query_string查询,不进行分词

最近在使用ELasitcsearch的时候,需要用到关键字搜索,因为是全字段搜索,就需要使用_all字段的query_string进行搜索. 但是在使用的时候,遇到问题了.我们的业务并不需要分词,我在各个字段也设置了,not_analyzed.但是在使用query_string对_all字段进行查询的时候, 发现结果还是分词的.最后在官网找到这么一段话: Remember that the _all field is just an analyzed string field. It uses

[Elasticsearch] 多字段搜索 (三) - multi_match查询和多数字段

multi_match查询 multi_match查询提供了一个简便的方法用来对多个字段执行相同的查询. NOTE 存在几种类型的multi_match查询,其中的3种正好和在"了解你的数据"一节中提到的几种类型相同:best_fields,most_fields以及cross_fields. 默认情况下,该查询以best_fields类型执行,它会为每个字段生成一个match查询,然后将这些查询包含在一个dis_max查询中.下面的dis_max查询: { "dis_max

[Elasticsearch] 全文搜索 (一) - 基础概念和match查询

全文搜索(Full Text Search) 现在我们已经讨论了搜索结构化数据的一些简单用例,是时候开始探索全文搜索了 - 如何在全文字段中搜索来找到最相关的文档. 对于全文搜索而言,最重要的两个方面是: 相关度(Relevance) 查询的结果按照它们对查询本身的相关度进行排序的能力,相关度可以通过TF/IDF,参见什么是相关度,地理位置的邻近程度(Proximity to a Geo-location),模糊相似性(Fuzzy Similarity)或者其它算法进行计算. 解析(Analys

Elasticsearch系列---多字段搜索

概要 本篇介绍一下multi_match的best_fields.most_fields和cross_fields三种语法的场景和简单示例. 最佳字段 bool查询采取"more-matches-is-better"匹配越多分越高的方式,所以每条match语句的评分结果会被加在一起,从而为每个文档提供最终的分数_score.能与两条语句同时匹配的文档会比只与一条语句匹配的文档得分要高,但有时这样也会带来一些与期望不符合的情况,我们举个例子: 我们以英文儿歌为案例背景,我们这样搜索: G

ElasticSearch(8)-分布式搜索

分布式搜索的执行方式 在继续之前,我们将绕道讲一下搜索是如何在分布式环境中执行的. 它比我们之前讲的基础的增删改查(create-read-update-delete ,CRUD)请求要复杂一些. 注意: 本章的信息只是出于兴趣阅读,使用Elasticsearch并不需要理解和记住这里的所有细节. 阅读这一章只是增加对系统如何工作的了解,并让你知道这些信息以备以后参考,所以别淹没在细节里. 一个CRUD操作只处理一个单独的文档.文档的唯一性由_index, _type和routing-value