[Elasticsearch] 全文搜索 (二) - 多词查询及查询的合并

多词查询(Multi-word Queries)

如果我们一次只能搜索一个词,那么全文搜索就会显得相当不灵活。幸运的是,通过match查询来实现多词查询也同样简单:

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "BROWN DOG!"
        }
    }
}

以上的查询会返回所有的四份文档:

{
  "hits": [
     {
        "_id":      "4",
        "_score":   0.73185337,
        "_source": {
           "title": "Brown fox brown dog"
        }
     },
     {
        "_id":      "2",
        "_score":   0.47486103,
        "_source": {
           "title": "The quick brown fox jumps over the lazy dog"
        }
     },
     {
        "_id":      "3",
        "_score":   0.47486103,
        "_source": {
           "title": "The quick brown fox jumps over the quick dog"
        }
     },
     {
        "_id":      "1",
        "_score":   0.11914785,
        "_source": {
           "title": "The quick brown fox"
        }
     }
  ]
}

文档4的相关度最高因为它包含了"brown"两次和"dog"一次。
文档2和文档3都包含了"brown""dog"一次,同时它们的title字段拥有相同的长度,因此它们的分值相同。
文档1只包含了"brown"

因为match查询需要查询两个词条 - ["brown","dog"] -
在内部它需要执行两个term查询,然后将它们的结果合并来得到整体的结果。因此,它会将两个term查询通过一个bool查询组织在一起,我们会在合并查询一节中详细介绍。

从上面的例子中需要吸取的经验是,文档的title字段中只需要包含至少一个指定的词条,就能够匹配该查询。如果匹配的词条越多,也就意味着该文档的相关度就越高。

提高精度(Improving
Precision)

匹配任何查询词条就算作匹配的话,会导致最终结果中有很多看似无关的匹配。它是一个霰弹枪式的策略(Shotgun Approach)。我们大概只想要显示包含了所有查询词条的文档。换言之,相比brown OR
dog
,我们更想要的结果是brown AND dog

match查询接受一个operator参数,该参数的默认值是"or"。你可以将它改变为"and"来要求所有的词条都需要被匹配:

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": {
                "query":    "BROWN DOG!",
                "operator": "and"
            }
        }
    }
}

match查询的结构需要被稍稍改变来容纳operator参数。

这个查询的结果会将文档1排除在外,因为它只包含了一个查询词条。

控制精度(Controlling
Precision)

在all和any中选择有种非黑即白的感觉。如果用户指定了5个查询词条,而一份文档只包含了其中的4个呢?将"operator"设置成"and"会将它排除在外。

有时候这正是你想要的,但是对于大多数全文搜索的使用场景,你会希望将相关度高的文档包含在结果中,将相关度低的排除在外。换言之,我们需要一种介于两者中间的方案。

match查询支持minimum_should_match参数,它能够让你指定有多少词条必须被匹配才会让该文档被当做一个相关的文档。尽管你能够指定一个词条的绝对数量,但是通常指定一个百分比会更有意义,因为你无法控制用户会输入多少个词条:

GET /my_index/my_type/_search
{
  "query": {
    "match": {
      "title": {
        "query":                "quick brown dog",
        "minimum_should_match": "75%"
      }
    }
  }
}

当以百分比的形式指定时,minimum_should_match会完成剩下的工作:在上面拥有3个词条的例子中,75%会被向下舍入到66.6%,即3个词条中的2个。无论你输入的是什么,至少有2个词条被匹配时,该文档才会被算作最终结果中的一员。

minimum_should_match参数非常灵活,根据用户输入的词条的数量,可以适用不同的规则。具体可以参考minimum_should_match参数的相关文档

为了更好地了解match查询是如何处理多词查询的,我们需要看看bool查询是如何合并多个查询的。

合并查询(Combining Queries)

合并过滤器中我们讨论了使用bool过滤器来合并多个过滤器以实现andornot逻辑。bool查询也做了类似的事,但有一个显著的不同。

过滤器做出一个二元的决定:这份文档是否应该被包含在结果列表中?而查询,则更加微妙。它们不仅要决定是否包含一份文档,还需要决定这份文档有多相关。

和过滤器类似,bool查询通过mustmust_not以及should参数来接受多个查询。比如:

GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "must":     { "match": { "title": "quick" }},
      "must_not": { "match": { "title": "lazy"  }},
      "should": [
                  { "match": { "title": "brown" }},
                  { "match": { "title": "dog"   }}
      ]
    }
  }
}

title字段中含有词条quick,且不含有词条lazy的任何文档都会被作为结果返回。目前为止,它的工作方式和bool过滤器十分相似。

差别来自于两个should语句,它表达了这种意思:一份文档不被要求需要含有词条brown或者dog,但是如果它含有了,那么它的相关度应该更高。

{
  "hits": [
     {
        "_id":      "3",
        "_score":   0.70134366,
        "_source": {
           "title": "The quick brown fox jumps over the quick dog"
        }
     },
     {
        "_id":      "1",
        "_score":   0.3312608,
        "_source": {
           "title": "The quick brown fox"
        }
     }
  ]
}

文档3的分值更高因为它包含了brown以及dog

分值计算(Score
Calculation)

bool查询通过将匹配的mustshould语句的_score相加,然后除以mustshould语句的总数来得到相关度分值_score

must_not语句不会影响分值;它们唯一的目的是将不需要的文档排除在外。

控制精度(Controlling
Precision)

所有的must语句都需要匹配,而所有的must_not语句都不能匹配,但是should语句需要匹配多少个呢?默认情况下,should语句一个都不要求匹配,只有一个特例:如果查询中没有must语句,那么至少要匹配一个should语句。

正如我们可以控制match查询的精度,我们也能够通过minimum_should_match参数来控制should语句需要匹配的数量,该参数可以是一个绝对数值或者一个百分比:

GET /my_index/my_type/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title": "brown" }},
        { "match": { "title": "fox"   }},
        { "match": { "title": "dog"   }}
      ],
      "minimum_should_match": 2
    }
  }
}

以上查询的而结果仅包含以下文档:

title字段包含: "brown"
AND "fox"
 或者 "brown" AND "dog" 或者 "fox"
AND "dog"

如果一份文档含有所有三个词条,那么它会被认为更相关。

时间: 2024-10-13 15:43:46

[Elasticsearch] 全文搜索 (二) - 多词查询及查询的合并的相关文章

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

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

[Elasticsearch] 全文搜索 (三) - match查询和bool查询的关系,提升查询子句

match查询是如何使用bool查询的 现在,你也许意识到了使用了match查询的多词查询只是简单地将生成的term查询包含在了一个bool查询中.通过默认的or操作符,每个term查询都以一个k语句被添加,所以至少一个should语句需要被匹配.以下两个查询是等价的: { "match": { "title": "brown fox"} } { "bool": { "should": [ { "

Elasticsearch 全文搜索

1,匹配查询(match) match查询主要的应用场景是进行全文搜索: // 1,初始化数据 DELETE /my_index PUT /my_index { "settings": { "number_of_shards": 1 }} POST /my_index/my_type/_bulk { "index": { "_id": 1 }} { "title": "The quick brow

[Elasticsearch] 全文搜索 (四) - 控制分析及相关度

控制分析(Controlling Analysis) 查询只能摘到真实存在于倒排索引(Inverted Index)中的词条(Term),因此确保相同的分析过程会被适用于文档的索引阶段和搜索阶段的查询字符串是很重要的,这样才能够让查询中的词条能够和倒排索引中的词条匹配. 尽管我们说的是文档(Document),解析器(Analyzer)是因字段而异的(Determined per Field).每个字段都能够拥有一个不同的解析器,通过为该字段配置一个特定的解析器或者通过依赖类型(Type),索引

Elasticsearch系列---搜索执行过程及scroll游标查询

概要 本篇主要介绍一下分布式环境中搜索的两阶段执行过程. 两阶段搜索过程 回顾我们之前的CRUD操作,因为只对单个文档进行处理,文档的唯一性很容易确定,并且很容易知道是此文档在哪个node,哪个shard中. 但搜索比CRUD复杂,符合搜索条件的文档,可能散落在各个node.各个shard中,我们需要找到匹配的文档,并且把从各个node,各个shard返回的结果进行汇总.排序,组成一个最终的结果排序列表,才算完成一个搜索过程.我们将按两阶段的方式对这个过程进行讲解. 查询阶段 假定我们的ES集群

Elasticsearch 全文搜索和keyword search字段的mapping定义

在ES5.0之前我们对于需要keyword search的字段都是这样定义的: { "field name":{ "type": "string", "index": "not_analyzed" } } 全文检索: { "field name":{ "type": "string" } } ES 5+: keyword search: { &qu

Sql Server 数据库建全文搜索

摘自:https://www.cnblogs.com/ljhdo/p/5041605.html SQL Server 的全文搜索(Full-Text Search)是基于分词的文本检索功能,依赖于全文索引.全文索引不同于传统的平衡树(B-Tree)索引和列存储索引,它是由数据表构成的,称作倒转索引(Invert Index),存储分词和行的唯一键的映射关系.倒转索引是在创建全文索引或更新全文索引时,由SQL Server自动创建和维护的.全文索引主要包含三种分析器:分词器(Word Breake

全文搜索存储引擎 Elasticsearch 一点点

开始请大家想一个问题,如何统计一个Web站点的有效PV? 针对用户请求的URL,统计时做模式匹配-------->即用户真正去打开一个站点的有效页面并对每个页面的入口的访问做一个统计浏览量: 简要搜索引擎 搜索引擎在互联网上特别多有专业(Startpage,Google,Yahoo,Baidu)等也有非专业开源(北大搜索.任何基于Lucene库的二次开发搜索代理引擎)等:其重点都是用来做海量数据搜索存储.分析,并且根据用户指定的filter来过滤出用户所需要的数据.而背后所需基础组件无外乎是 索

ElasticSearch基础3:全文搜索

全文搜索 所有查询会或多或少的执行相关度计算,但不是所有查询都有分析阶段.和一些特殊的完全不会对文本进行操作的查询(如 bool 或 function_score )不同,文本查询可以划分成两大家族: 基于词项的查询 如 term 或 fuzzy 这样的底层查询不需要分析阶段,它们对单个词项进行操作.用 term 查询词项 Foo 只要在倒排索引中查找 准确词项 ,并且用 TF/IDF 算法为每个包含该词项的文档计算相关度评分 _score .记住 term 查询只对倒排索引的词项精确匹配,这点