高低频词: 分而治之 (devide and conquer, 分治法) edit

在查询字符串中的词项可以分为更重要(低频词)和次重要(高频词)这两类。 只与次重要词项匹配的文档很有可能不太相关。实际上,我们想要文档能尽可能多的匹配那些更重要的词项。

match 查询接受一个参数 cutoff_frequency ,从而可以让它将查询字符串里的词项分为低频和高频两组。低频组(更重要的词项)组成 bulk 大量查询条件,而高频组(次重要的词项)只会用来评分,而不参与匹配过程。通过对这两组词的区分处理,我们可以在之前慢查询的基础上获得巨大的速度提升。

领域相关的停用词(Domain-Specific Stopwords)

以下面查询为例:

{
  "match": {
    "text": {
      "query": "Quick and the dead",
      "cutoff_frequency": 0.01 
    }
}

任何词项出现在文档中超过1%,被认为是高频词。cutoff_frequency 配置可以指定为一个分数( 0.01 )或者一个正整数( 5 )。

此查询通过 cutoff_frequency 配置,将查询条件划分为低频组( quick , dead )和高频组( and , the )。然后,此查询会被重写为以下的 bool 查询:

{
  "bool": {
    "must": { 
      "bool": {
        "should": [
          { "term": { "text": "quick" }},
          { "term": { "text": "dead"  }}
        ]
      }
    },
    "should": { 
      "bool": {
        "should": [
          { "term": { "text": "and" }},
          { "term": { "text": "the" }}
        ]
      }
    }
  }
}

必须匹配至少一个低频/更重要的词项。

高频/次重要性词项是非必须的。

must 意味着至少有一个低频词— quick 或者 dead —必须出现在被匹配文档中。所有其他的文档被排除在外。 should 语句查找高频词 andthe ,但也只是在 must 语句查询的结果集文档中查询。 should 语句的唯一的工作就是在对如 Quick _and the_ dead_The_ quick but dead 语句进行评分时,前者得分比后者高。这种方式可以大大减少需要进行评分计算的文档数量。

将操作符参数设置成 and 会要求所有低频词都必须匹配,同时对包含所有高频词的文档给予更高评分。但是,在匹配文档时,并不要求文档必须包含所有高频词。如果希望文档包含所有的低频和高频词,我们应该使用一个 bool 来替代。正如我们在and 操作符中看到的,它的查询效率已经很高了。

控制精度edit

minimum_should_match 参数可以与 cutoff_frequency 组合使用,但是此参数仅适用于低频词。如以下查询:

{
  "match": {
    "text": {
      "query": "Quick and the dead",
      "cutoff_frequency": 0.01,
      "minimum_should_match": "75%"
    }
}

将被重写为如下所示:

{
  "bool": {
    "must": {
      "bool": {
        "should": [
          { "term": { "text": "quick" }},
          { "term": { "text": "dead"  }}
        ],
        "minimum_should_match": 1 
      }
    },
    "should": { 
      "bool": {
        "should": [
          { "term": { "text": "and" }},
          { "term": { "text": "the" }}
        ]
      }
    }
  }
}

因为只有两个词,原来的75%向下取整为 1 ,意思是:必须匹配低频词的两者之一。

高频词是可选的,并且仅用于评分使用。

高频词 (Only High-Frequency Terms) edit

当使用 or 查询高频词条,如对 To be, or not to be 进行查询时性能最差。只是为了返回最匹配的前十个结果就对只是包含这些词的所有文档进行评分是盲目的。我们真正的意图是查询整个词条出现的文档,所以在这种情况下,在不存在低频词的情况下,这个查询需要重写为所有高频词条都必须包含:

{
  "bool": {
    "must": [
      { "term": { "text": "to" }},
      { "term": { "text": "be" }},
      { "term": { "text": "or" }},
      { "term": { "text": "not" }},
      { "term": { "text": "to" }},
      { "term": { "text": "be" }}
    ]
  }
}

对常用词(Common Terms)进行更多控制edit

尽管高频/低频的功能在 match 查询中是有用的,有时我们还希望能对它有更多的控制,想控制它对高频和低频词分组的行为。 match 查询针对 common 词项查询提供了一组功能。

例如,我们可以让所有低频词都必须匹配,而只对那些包括超过 75% 的高频词文档进行评分:

{
  "common": {
    "text": {
      "query":                  "Quick and the dead",
      "cutoff_frequency":       0.01,
      "low_freq_operator":      "and",
      "minimum_should_match": {
        "high_freq":            "75%"
      }
    }
  }
}

更多配置项参见 common terms query