如何在 Elasticsearch 中搜索不匹配大小写的精确文本



我想在Elasticsearch中搜索用户名。为此,我想匹配确切的用户名,忽略其大小写,无论它是大写还是小写,我只想找到该用户名。我为此使用以下查询:

QueryBuilder queryBuilder = QueryBuilders.termQuery("user_name.keyword", userName);
NativeSearchQuery build = new NativeSearchQueryBuilder().withQuery(queryBuilder).build();
List<Company> companies = elasticsearchTemplate.queryForList(build, User.class);

但它也与案例的确切词相匹配。例如:如果用户名是"Ram",而我搜索"ram",那么它不会返回该名称。如果我搜索"Ram",那么它会给我结果。但我希望它只匹配这个词,而不是这个词的情况。拜托,有人,帮我解决这个问题。我搜索了很多,但找不到任何解决方案。

问题是您正在使用user_name.keywordterms查询。Terms查询匹配确切的单词,而不是您可以使用MatchQueryBuilder查询:

法典:

QueryBuilder queryBuilder = QueryBuilders.matchQuery("user_name", userName);
NativeSearchQuery build = new NativeSearchQueryBuilder().withQuery(queryBuilder).build();
List<Company> companies = elasticsearchTemplate.queryForList(build, User.class);

使用.keyword字段时,弹性不会分析文本,但如果您使用文本字段,ElasticSerach 会使用该字段的默认分析器分析文本。默认分析器基本上以小写形式转换文本并从中删除停用词。你可以从这里阅读它:https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-analyzer.html

由于您要执行不区分大小写的搜索,因此无需使用.keyword.

此外,terms查询与确切的术语匹配,但同样,由于您要进行不区分大小写的搜索,因此您应该match查询,默认情况下,该查询也会在内部将搜索文本转换为小写,然后在字段中搜索该文本。

而且,现在由于您的字段和搜索词都是小写的,您可以进行不区分大小写的搜索,但这不会完全匹配

要进行完全不区分大小写的匹配,您需要更新索引并在关键字字段中使用规范化器,以保证分析链生成单个标记和不区分大小写的搜索。你可以从这里阅读更多关于它的信息。

索引创建:

curl -X PUT "localhost:9200/<index-name>" -H 'Content-Type: application/json' -d 
{
"settings": {
"analysis": {
"normalizer": {
"case_insensitive_normalizer": {
"type": "custom",
"filter": [
"lowercase"
]
}
}
}
},
"mappings": {
"properties": {
"user_name": {
"type": "keyword",
"normalizer": "case_insensitive_normalizer"
}
}
}
}

我已经索引了这些文件:

文档1 :

{
"user_name": "Ram"
} 

文档2 :

{
"user_name": "Ram Mohan"
}

搜索查询 :

{
"query" : {
"match" : {
"user_name" : "ram"
}
}
}

结果:

"hits": [
{
"_source": {
"user_name": "Ram"
}
}
]

尝试在索引映射中使用小写标记筛选器。

https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lowercase-tokenfilter.html

这种令牌过滤器在索引和搜索中都应用,因此"Ram"将被索引为"ram",然后如果您搜索"rAm",它将更改为"ram",以便它到达您的文档。

如果要对关键字字段进行不区分大小写的匹配,则可以使用带有小写筛选器的规范化器

关键字字段的规范化器属性类似于分析器 除了它保证分析链产生单个 令 牌。

{
"settings": {
"analysis": {
"normalizer": {
"lowercase_normalizer": {
"type": "custom",
"filter": [
"lowercase"
]
}
}
}
},
"mappings": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"normalizer": "lowercase_normalizer"
}
}
}
}
}
}

数据

POST index41/_doc
{
"name":"Ram"
}

查询:

{
"query": {
"term": {
"name.keyword": {
"value": "ram"
}
}
}
}

结果:

"hits" : [
{
"_index" : "index41",
"_type" : "_doc",
"_id" : "IyieGHIBZsF59xnAhb47",
"_score" : 0.6931471,
"_source" : {
"name" : "Ram"
}
}
]

您可以简单地在用户名字段上使用文本字段,文本字段默认使用标准分析器,将标记小写,然后匹配查询应用相同的分析器,该分析器使用索引时间(在本例中为标准(,这将为您提供不区分大小写的搜索。

使用标准分析器生成的令牌

POST /_analyzer
{
"text" : "ram",
"analyzer" : "standard"
}
{
"tokens": [
{
"token": "ram",
"start_offset": 0,
"end_offset": 3,
"type": "<ALPHANUM>",
"position": 0
}
]
}

最新更新