为什么 ElasticSearch 匹配查询返回所有结果?
Why is ElasticSearch match query returning all results?
我有以下 ElasticSearch 查询,我认为 return 所有匹配 email 字段等于 myemails@email.com
"query": {
"bool": {
"must": [
{
"match": {
"email": "myemail@gmail.com"
}
}
]
}
}
正在搜索的 user 类型的映射如下:
{
"users": {
"mappings": {
"user": {
"properties": {
"email": {
"type": "string"
},
"name": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
},
"nickname": {
"type": "string"
},
}
}
}
}
}
以下是 returnElasticSearch
的结果示例
[{
"_index": "users",
"_type": "user",
"_id": "54b19c417dcc4fe40d728e2c",
"_score": 0.23983537,
"_source": {
"email": "johnsmith@gmail.com",
"name": "John Smith",
"nickname": "jsmith",
},
{
"_index": "users",
"_type": "user",
"_id": "9c417dcc4fe40d728e2c54b1",
"_score": 0.23983537,
"_source": {
"email": "myemail@gmail.com",
"name": "Walter White",
"nickname": "wwhite",
},
{
"_index": "users",
"_type": "user",
"_id": "4fe40d728e2c54b19c417dcc",
"_score": 0.23983537,
"_source": {
"email": "JimmyFallon@gmail.com",
"name": "Jimmy Fallon",
"nickname": "jfallon",
}]
根据上述查询,我认为这需要与 'myemail@gmail.com' 完全匹配作为电子邮件 属性 值。
ElasticSearch DSL 查询需要如何更改才能仅 return 完全匹配 电子邮件。
电子邮件字段已标记化,这就是出现此异常的原因。
所以当你索引
时发生了什么
"myemail@gmail.com" => ["myemail" , "gmail.com" ]
这样,如果您搜索 myemail 或 gmail.com,您将获得正确的匹配。
所以发生的事情是,当您搜索 john@gmail.com 时,分析器也应用于搜索查询。
因此它被分解成
"john@gmail.com" => ["john" , "gmail.com" ]
这里因为 "gmail.com" 标记在搜索词和索引词中很常见,你会得到一个匹配项。
要克服这种行为,声明电子邮件;字段为 not_analyzed。标记化不会发生,整个字符串将被索引。
和"not_analyzed"
"john@gmail.com" => ["john@gmail.com"]
所以修改映射到这个,你应该很好 -
{
"users": {
"mappings": {
"user": {
"properties": {
"email": {
"type": "string",
"index": "not_analyzed"
},
"name": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
},
"nickname": {
"type": "string"
}
}
}
}
}
}
我已经更准确地描述了问题以及解决问题的另一种方法here。
我有以下 ElasticSearch 查询,我认为 return 所有匹配 email 字段等于 myemails@email.com
"query": {
"bool": {
"must": [
{
"match": {
"email": "myemail@gmail.com"
}
}
]
}
}
正在搜索的 user 类型的映射如下:
{
"users": {
"mappings": {
"user": {
"properties": {
"email": {
"type": "string"
},
"name": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
},
"nickname": {
"type": "string"
},
}
}
}
}
}
以下是 returnElasticSearch
的结果示例 [{
"_index": "users",
"_type": "user",
"_id": "54b19c417dcc4fe40d728e2c",
"_score": 0.23983537,
"_source": {
"email": "johnsmith@gmail.com",
"name": "John Smith",
"nickname": "jsmith",
},
{
"_index": "users",
"_type": "user",
"_id": "9c417dcc4fe40d728e2c54b1",
"_score": 0.23983537,
"_source": {
"email": "myemail@gmail.com",
"name": "Walter White",
"nickname": "wwhite",
},
{
"_index": "users",
"_type": "user",
"_id": "4fe40d728e2c54b19c417dcc",
"_score": 0.23983537,
"_source": {
"email": "JimmyFallon@gmail.com",
"name": "Jimmy Fallon",
"nickname": "jfallon",
}]
根据上述查询,我认为这需要与 'myemail@gmail.com' 完全匹配作为电子邮件 属性 值。
ElasticSearch DSL 查询需要如何更改才能仅 return 完全匹配 电子邮件。
电子邮件字段已标记化,这就是出现此异常的原因。 所以当你索引
时发生了什么"myemail@gmail.com" => ["myemail" , "gmail.com" ]
这样,如果您搜索 myemail 或 gmail.com,您将获得正确的匹配。 所以发生的事情是,当您搜索 john@gmail.com 时,分析器也应用于搜索查询。 因此它被分解成
"john@gmail.com" => ["john" , "gmail.com" ]
这里因为 "gmail.com" 标记在搜索词和索引词中很常见,你会得到一个匹配项。
要克服这种行为,声明电子邮件;字段为 not_analyzed。标记化不会发生,整个字符串将被索引。
和"not_analyzed"
"john@gmail.com" => ["john@gmail.com"]
所以修改映射到这个,你应该很好 -
{
"users": {
"mappings": {
"user": {
"properties": {
"email": {
"type": "string",
"index": "not_analyzed"
},
"name": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
},
"nickname": {
"type": "string"
}
}
}
}
}
}
我已经更准确地描述了问题以及解决问题的另一种方法here。