如何在 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.keyword
和 terms
查询。 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"
}
}
]
我想在 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.keyword
和 terms
查询。 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"
}
}
]