我在通配符查询搜索中遇到一些问题。
我的目的是,如果我搜索
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_phrase 或 term 查询,但这只是为了理解为什么这个简单的情况不起作用)。 如果我尝试少用一些词,比如:
*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
分析仪就无法工作,所以我认为这不是一个好的解决方案。
您有两个选择:
首先是使用
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
分析器,并将您的文本标记为多个术语和索引,因此它适用于一个术语而不是多个术语。
性能影响
不建议使用以*
或
?
开头的通配符,因为它会影响搜索性能。以下是文档中提到的警告内容:
避免以 * 或 ? 开始模式。这可以增加迭代次数 需要找到匹配的术语并且搜索性能缓慢。