词项的分别管理
在查询字符串中的词项可以分为更重要(低频词)和次重要(高频词)这两类。只与次重要词项匹配的文档很有可能不太相关。实际上,我们想要文档能尽可能多的匹配那些更重要的词项。
match
查询接受一个参数cutoff_frequency
,从而可以让它将查询字符串里的词项分为低频和高频两组。低频组(更重要的词项)组成 bulk
大量查询条件,而高频组(次重要的词项)只会用来评分,而不参与匹配过程。通过对这两组词的区分处理,我们可以在之前慢查询的基础上获得巨大的速度提升。
领域相关的停用词(Domain-Specific Stopwords)
cutoff_frequency
配置的好处是,你在 特定领域 使用停用词不受约束。(((“domain specific stopwords”)))(((“stopwords”, “domain specific”)))例如,关于电影网站使用的词 movie 、 color 、 black 和 white ,这些词我们往往认为几乎没有任何意义。使用 stop
词汇单元过滤器,这些特定领域的词必须手动添加到停用词列表中。然而 cutoff_frequency
会查看索引里词项的具体频率,这些词会被自动归类为 高频词汇 。
以下面查询为例:
{
"match": {
"text": {
"query": "Quick and the dead",
"cutoff_frequency": 0.01 (1)
}
}
<1> 任何词项出现在文档中超过1%,被认为是高频词。cutoff_frequency
配置可以指定为一个分数( 0.01
)或者一个正整数( 5
)。
此查询通过 cutoff_frequency
配置,将查询条件划分为低频组( quick
, dead
)和高频组( and
, the
)。然后,此查询会被重写为以下的 bool
查询:
{
"bool": {
"must": { <1>
"bool": {
"should": [
{ "term": { "text": "quick" }},
{ "term": { "text": "dead" }}
]
}
},
"should": { <2>
"bool": {
"should": [
{ "term": { "text": "and" }},
{ "term": { "text": "the" }}
]
}
}
}
}
<1> 必须匹配至少一个低频/更重要的词项。
<2> 高频/次重要性词项是非必须的。
must
意味着至少有一个低频词— quick
或者 dead
—必须出现在被匹配文档中。所有其他的文档被排除在外。 should
语句查找高频词 and
和 the
,但也只是在 must
语句查询的结果集文档中查询。 should
语句的唯一的工作就是在对如 Quick _and the_ dead
和 _The_ quick but dead
语句进行评分时,前者得分比后者高。这种方式可以大大减少需要进行评分计算的文档数量。
[TIP]
将操作符参数设置成 and
会要求所有低频词都必须匹配,同时对包含所有高频词的文档给予更高评分。但是,在匹配文档时,并不要求文档必须包含所有高频词。如果希望文档包含所有的低频和高频词,我们应该使用一个 bool
来替代。正如我们在 stopwords-and中看到的,它的查询效率已经很高了。
控制精度
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 (1)
}
},
"should": { (2)
"bool": {
"should": [
{ "term": { "text": "and" }},
{ "term": { "text": "the" }}
]
}
}
}
}
<1> 因为只有两个词,原来的75%向下取整为 1
,意思是:必须匹配低频词的两者之一。
<2> 高频词仍可选的,并且仅用于评分使用。
高频词
当使用 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" }}
]
}
}
对常用词使用更多控制(More Control with Common Terms)
尽管高频/低频的功能在 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%"
}
}
}
}
更多配置项参见 {ref}/query-dsl-common-terms-query.html[common
terms query]。