查询弹性搜索以使所有分析的 ngram 标记匹配



>我使用 nGram 分析器(仅发出三元语法(索引了一些数据,以完全按照 ES 指南中的描述解决复合词问题。

但是,这并不像预期的那样工作:根据匹配查询将返回至少匹配一个 nGram 令牌(每个单词(的所有文档。

例:

让我们使用那个 nGram 分析器将这两个索引文档与一个字段放在一起:

POST /compound_test/doc/_bulk
{ "index": { "_id": 1 }}
{ "content": "elasticsearch is awesome" }
{ "index": { "_id": 2 }}
{ "content": "some search queries don't perform good" }

现在,如果我运行以下查询,我会得到两个结果:

"match": {
"content": {
"query": "awesome search",
"minimum_should_match": "100%"
}
}

由此构造的查询可以表示如下:

(awe OR wes OR eso OR ome) AND (sea OR ear OR arc OR rch)

这就是第二个文档匹配的原因(它包含"一些"和"搜索"(。它甚至可以将文档与包含标记"som"和"rch"的单词匹配。

我真正想要的是一个查询,其中每个分析的令牌必须匹配(在最好的情况下取决于最小应该匹配(,所以像这样:

"match": {
"content": {
"query": "awe wes eso ome sea ear arc rch",
"analyzer": "whitespace", 
"minimum_should_match": "100%"
}
}

..无需实际"手动"创建该查询/在客户端对其进行预分析。

可以在 https://pastebin.com/97QxfaSb 中找到重现该行为的所有设置和数据

有这种可能吗?

在写问题时,我意外找到了答案:

如果 ngram 分析器使用 ngram 过滤器生成三元组(如指南中所述(,它将按上述方式工作。(我猜是因为实际的令牌不是单个 ngram,而是所有创建的 ngram 的组合(

若要实现所需的行为,分析器必须使用 ngram 标记器:

"tokenizer": {
"trigram_tokenizer": {
"type": "ngram",
"min_gram": 3,
"max_gram": 3,
"token_chars": [
"letter",
"digit"
]
}
},
"analyzer": {
"trigrams_with_tokenizer": {
"type": "custom",
"tokenizer": "trigram_tokenizer" 
}
}

使用这种方式生成令牌将在酷儿该字段时产生预期的结果。

最新更新