我看过每一篇文章,发现我可以找到有关执行完全匹配,不区分大小写的查询的信息,但是在实现时,它们并不能满足我的需求。
在将此问题标记为重复之前,请阅读整篇文章。
给出用户名,我想查询我的Elasticsearch数据库以仅返回与用户名完全匹配但不区分大小写的文档。
我尝试为我的lowercase
属性指定一个username
分析器,并使用match
查询来实现此行为。虽然这解决了区分大小写的匹配问题,但在完全匹配时失败。
我研究过使用lowercase
规范化器,但这会使索引中的所有用户名都变为小写,因此当我聚合用户名时,它们将以小写形式返回,这不是我想要的。我需要在用户名中保留每个字母的原始大小写。
POST {elastic}/users/_doc
{
"email": "random@email.com",
"username": "UsErNaMe",
"password": "1234567"
}
此文档将按照原样存储在名为users
的索引中。
GET {frontend}/user/UsErNaMe
应该返回
{
"email": "random@email.com",
"username": "UsErNaMe",
"password": "1234567"
}
和
GET {frontend}/user/username
应该返回
{
"email": "random@email.com",
"username": "UsErNaMe",
"password": "1234567"
}
和
GET {frontend}/user/USERNAME
应该返回
{
"email": "random@email.com",
"username": "UsErNaMe",
"password": "1234567"
}
和
GET {frontend}/user/UsErNaMe $RaNdoM LeTteRs
应该不返回任何内容。
谢谢。
答案 0 :(得分:3)
要实现不区分大小写的精确匹配,您需要定义自己的分析器。分析器需要执行两个操作:
以上两个可以通过以下方式实现:
lowercase
过滤器。tokenizer
设置为keyword
,这将确保在应用小写过滤器后生成输入值的单个标记。现在,可以将此自定义分析器应用于需要区分大小写的精确搜索的文本字段。
因此,您可以在下面使用索引来创建索引:
PUT test
{
"settings": {
"analysis": {
"analyzer": {
"case_insensitive_analyzer": {
"type": "custom",
"filter": [
"lowercase"
],
"tokenizer": "keyword"
}
}
}
},
"mappings": {
"_doc": {
"properties": {
"email": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"username": {
"type": "text",
"analyzer": "case_insensitive_analyzer"
},
"password": {
"type": "keyword"
}
}
}
}
}
在上面的case_insensitive_analyzer
中是必需的分析器,如您所见,它已应用在username
字段中。
因此,当您索引文档如下时:
PUT test/_doc/1
{
"email": "random@email.com",
"username": "UsErNaMe",
"password": "1234567"
}
对于字段username
,输入为UsErNaMe
。分析器首先在输入lowercase
上应用UsErNaMe
过滤器,得到值username
。现在,在此值username
上应用keyword
令牌生成器,该令牌生成器什么也不做,只输出应用了过滤器后获得的值作为单个令牌,即username
。
现在您可以使用以下匹配查询来搜索用户名字段:
GET test/_doc/_search
{
"query": {
"match": {
"username": "USERNAME"
}
}
}
使用上面的命令将为您提供所需的输出。将上述查询中的USERNAME
替换为username
或UsErNaMe
或USERname
,所有文件都会匹配。原因是,在搜索中是否未明确指定分析器时,elasticsearch在建立索引时会使用应用于该字段的分析器。在上述情况下,当对字段username
进行搜索时,case_insensitive_analyzer
将应用于输入值,即USERNAME
,这将导致标记username
并因此导致匹配。