通配符查询 Elasticsearch 不适用于多单词值

问题描述 投票:0回答:2

我在通配符查询搜索中遇到一些问题。

我的目的是,如果我搜索

word1 word2 word3
,我将找到所有在组成整个字符串的每个单词前后可以有 前缀和后缀的结果。

我的索引的结构是:

{ "my_index": { "aliases": {}, "mappings": { "properties": { "attributes": { "properties": { "name": { "properties": { "value": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } }, } } } }, "settings": { ... } } }
所以我有一个字段

attributes.name

(文本),我想在其中匹配值。

我的索引包含

attributes.name

 值为:
的对象

  • word1
    ,
  • word1suffix
    ,
  • word1 word2
    ,
  • word1 word2suffix
    
    
  • word1 word2 word3
    .
在运行搜索之前,我在内部

在每个单词之前和之后添加通配符

word1 word2 word3

 => 
*word1* *word2* *word3*

然后我运行这个查询:

{ "size": 10, "index": "my_index", "body": { "query": { "bool": { "should": [ { "wildcard": { "attributes.name.value": { "value": "*word1* *word2* *word3*", "rewrite": "constant_score" } } } ], "must": [], "minimum_should_match": 1 } } }, "explain": false }
我面临的奇怪的事情是,即使在索引中我正好有一个名为 

word1 word2 word3

 的对象,
我无法通过这种通配符搜索找到它(我知道在这种情况下,最好是 match_phraseterm 查询,但这只是为了理解为什么这个简单的情况不起作用)。

如果我尝试少用一些词,比如:

  • *word1*
    ,我发现
    word1
    word1suffix
    word1 word2
    word1 word2suffix
    
    
  • *word1* *word2*
    ,我发现
    word1 word2
    word1 word2suffix
    
    
  • *word1* *word2* *word3*

所以当我搜索包含太多单词的结果时,这种奇怪的行为似乎就开始了。

只是为了调试,我的值以这种方式存储在索引中:

{ "attributes": { "name": [{ "value": "word1 word2 word3" }], } }

最后考虑:我通过在word1 word2 word3

字段中搜索(我认为
attributes.name.value.keyword
是在每个文本字段的索引中自动生成的)而不是
.keyword
找到了
attributes.name.value
。问题是,如果我使用 
.keyword
 分析仪就无法工作,所以我认为这不是一个好的解决方案。

elasticsearch full-text-search wildcard keyword elasticsearch-query
2个回答
7
投票
通配符查询基于模式工作,因此它将整个查询视为一个模式,因此当您添加多个单词时它可能不匹配。

您有两个选择:

首先是使用

query_string

类型的查询,如下所示,您可以根据需要将
default_operator
的值设置为
AND
OR
。这将仅在内部创建 
bool
 查询:

{ "query": { "bool": { "should": [ { "query_string": { "default_field": "value", "query": "*word1* *word2* *word3*", "default_operator": "AND" } } ] } } }
其次,您可以在 

wildcard

 内有多个 
must
 查询,用于 
AND
 查询,在 
should
 内用于 
OR
 查询条件:

{ "query": { "bool": { "must": [ { "wildcard": { "value": { "value": "*word1*" } } }, { "wildcard": { "value": { "value": "*word2*" } } }, { "wildcard": { "value": { "value": "*word3*" } } } ] } } }

更新

我通过在现场搜索设法找到了

word1 word2 word3

attributes.name.value.keyword
(我认为
.keyword
会自动
在每个文本字段的索引中生成)而不是
attributes.name.value
。问题是,如果我使用 
.keyword
分析仪不起作用,所以我认为这不是一个好的解决方案。

是的,如果您没有配置

mapping

,那么elastic会自动为每个字段创建映射,如果发现该字段为
text
类型,那么它也会创建一个具有
keyword
类型的内部字段。

它正在工作,因为

keyword

 字段不应用任何分析器,它会寻找完全匹配。如果您尝试使用多个术语对 
wildcard
 字段进行 
attributes.name.value.keyword
 查询,那么它会起作用,但区分大小写。因此,如果您有像 
word1 word2 word3
 这样的字段值,那么 
*word1* *word2* *word3*
 此查询将起作用,但 
*Word1* *word2* *word3*
 此查询将不起作用。 (参见 
W
 是大写)。

为什么它在 text

 类型字段上不起作用?

因为

wildcard

查询是术语级别查询,并且在查询时不应用任何
analyzer
。它将把您的整个查询视为一种模式。您正在匹配 
text
 类型字段的查询,该字段在索引时使用 
standard
 分析器,并将您的文本标记为多个术语和索引,因此它适用于一个术语而不是多个术语。

性能影响

不建议使用以

*

?
开头的通配符,因为它会影响搜索性能。以下是文档中提到的警告内容:

避免以 * 或 ? 开始模式。这可以增加迭代次数 需要找到匹配的术语并且搜索性能缓慢。


0
投票
query_string 也对我有用。但是,您能否解释一下 query_string 与通配符搜索有何不同,以及如果我们使用通配符搜索而不是基于术语的搜索,我们是否会丢失任何内容?

© www.soinside.com 2019 - 2024. All rights reserved.