我查看了每篇文章和帖子,我可以找到关于执行完全匹配,不区分大小写的查询,但在实现时,它们不会执行我正在寻找的内容。
在将此问题标记为重复之前,请阅读整篇文章。
给定用户名,我想查询我的Elasticsearch数据库,只返回与用户名完全匹配的文档,但也不区分大小写。
我已经尝试为我的lowercase
属性指定username
分析器并使用match
查询来实现此行为。虽然这解决了不区分大小写匹配的问题,但它在完全匹配时失败。
我研究了使用lowercase
规范化器,但这会使我的所有用户名在索引之前都是小写的,所以当我聚合用户名时,它们将以小写形式返回,这不是我想要的。我需要保留用户名中每个字母的原始大小写。
POST {elastic}/users/_doc
{
"email": "[email protected]",
"username": "UsErNaMe",
"password": "1234567"
}
该文档将完全按照它的方式存储在名为users
的索引中。
GET {frontend}/user/UsErNaMe
应该回来
{
"email": "[email protected]",
"username": "UsErNaMe",
"password": "1234567"
}
和
GET {frontend}/user/username
应该回来
{
"email": "[email protected]",
"username": "UsErNaMe",
"password": "1234567"
}
和
GET {frontend}/user/USERNAME
应该回来
{
"email": "[email protected]",
"username": "UsErNaMe",
"password": "1234567"
}
和
GET {frontend}/user/UsErNaMe $RaNdoM LeTteRs
不应该退货。
谢谢。
要实现不区分大小写的精确匹配,您需要定义自己的分析器。分析仪需要执行两个操作:
以上两点可以通过以下方式实现:
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": "[email protected]",
"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
并因此匹配。