我看过每一篇文章,发现可以执行精确匹配,不区分大小写的查询,但是在实现时,它们并不能满足我的要求。
在将此问题标记为重复之前,请阅读整篇文章。
给定一个用户名,我想查询我的Elasticsearch数据库以仅返回一个与该用户名完全匹配但不区分大小写的文档。
我尝试lowercase为username属性指定分析器,并使用match查询来实现此行为。虽然这解决了区分大小写的匹配问题,但在精确匹配时失败了。
lowercase
username
match
我考虑使用lowercase规范化程序,但这会使索引中的所有用户名都变为小写,因此当我聚合用户名时,它们将以小写形式返回,这不是我想要的。我需要在用户名中保留每个字母的原始大小写。
POST {elastic}/users/_doc { "email": "random@email.com", "username": "UsErNaMe", "password": "1234567" }
该文档将存储在users准确地称为索引的索引中。
users
GET {frontend}/user/UsErNaMe
应该回来
{ "email": "random@email.com", "username": "UsErNaMe", "password": "1234567" }
和
GET {frontend}/user/username
GET {frontend}/user/USERNAME
GET {frontend}/user/UsErNaMe $RaNdoM LeTteRs
应该 不 返回任何东西。
谢谢。
要实现不区分大小写的精确匹配,您需要定义自己的分析器。分析仪需要执行两个操作:
以上两个可以通过以下方式实现:
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现场应用。
case_insensitive_analyzer
因此,当您为文档编制索引时,如下所示:
PUT test/_doc/1 { "email": "random@email.com", "username": "UsErNaMe", "password": "1234567" }
对于该字段username,输入为UsErNaMe。分析仪首先lowercase对输入UsErNaMe值应用过滤器,以得出值username。现在,在此值username上应用keyword令牌化器,该令牌化器什么也不做,只是将应用过滤器后获得的值作为单个令牌输出username。
UsErNaMe
现在,您可以使用以下匹配查询来搜索用户名字段:
GET test/_doc/_search { "query": { "match": { "username": "USERNAME" } } }
使用上面的将为您提供所需的输出。更换USERNAME上面的查询中username或UsErNaMe或USERname全部将匹配文档。原因是,在搜索中是否未明确指定分析器时,elasticsearch在建立索引时会使用应用于该字段的分析器。在上述情况下,当对field进行搜索时username,case_insensitive_analyzer将应用于输入值USERNAME,即将导致标记username并因此导致匹配。
USERNAME
USERname