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

How to search exact text without matching case in 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" 那么它就会给我结果。但我希望它只匹配单词而不是那个单词的大小写。 请哪位大侠帮我解决这个问题。我搜索了很多但找不到任何解决方案。

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

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

这样的标记过滤器同时应用于索引和搜索,因此 "Ram" 将被索引为 "ram",然后如果您要搜索 "rAm",它将被更改为 "ram" 所以它会打到你的文件上。

您可以简单地在用户名字段上使用文本字段,文本字段由 default standard analyzer 使用,将标记小写,然后匹配查询应用与索引时间相同的分析器(在这种情况下, standard) 这将为您提供不区分大小写的搜索。

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

POST /_analyzer

{
    "text" : "ram",
    "analyzer" : "standard"
}

{
    "tokens": [
        {
            "token": "ram",
            "start_offset": 0,
            "end_offset": 3,
            "type": "<ALPHANUM>",
            "position": 0
        }
    ]
}

问题是您正在使用 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 字段时,elastic 不会分析文本,但如果您使用文本字段,ElasticSerach 会使用该字段上的默认分析器分析您的文本。默认分析器基本上将您的文本转换为小写并从中删除停用词。你可以从这里阅读它:https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-standard-analyzer.html

因为你想进行不区分大小写的搜索所以你不需要使用 .keyword.

此外,terms 查询匹配精确的字词,但再次因为你想进行不区分大小写的搜索,你应该 match 查询,默认情况下也会在内部将你的搜索文本转换为小写,然后搜索该文本的字段。

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

要进行完全不区分大小写的匹配,您需要更新索引并在关键字字段中使用规范器,以确保分析链生成单个标记和不区分大小写的搜索。您可以从 here.

阅读更多相关信息

索引创建:

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"
                }
            }
]

如果要对关键字字段进行不区分大小写的匹配,可以使用 normalizer 和小写过滤器

The normalizer property of keyword fields is similar to analyzer except that it guarantees that the analysis chain produces a single token.

{
  "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"
        }
      }
    ]