匹配查询中的所有确切单词
Match all exact words in a query
我想使用 ElasticSearch Java API 创建一个查询,它只匹配 (1) 完整的单词和 (2) 来自搜索查询的所有单词。这是一个例子:
正文:
hello wonderful world
这些应该匹配:
hello
hello wonderful
hello world
wonderful world
hello wonderful world
wonderful
world
这些不应该匹配:
hell
hello fniefsgbsugbs
我尝试了以下参数进行匹配查询,但它仍然与上面的两个示例匹配。
这是使用 ElasticSearch 7.7.1 生成查询的代码 Java API:
import org.elasticsearch.index.query.QueryBuilders
...
QueryBuilders.matchQuery(field, query)
.autoGenerateSynonymsPhraseQuery(false)
.fuzziness(0)
.prefixLength(0)
.fuzzyTranspositions(false)
.operator(Operator.AND)
.minimumShouldMatch("100%")
这将生成此查询:
{
"size": 100,
"query": {
"bool": {
"filter": [
{
"match": {
"searchableText": {
"query": "hell",
"operator": "AND",
"fuzziness": "0",
"prefix_length": 0,
"max_expansions": 50,
"minimum_should_match": "100%",
"fuzzy_transpositions": false,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": false,
"boost": 1
}
}
}
]
}
}
}
有人可以帮我找到一个好的解决方案吗?
编辑: 以下是设置和映射(我删除了与 searchableText
无关的所有内容以使其尽可能小):
{
"settings": {
"analysis": {
"normalizer": {
"lowercase_normalizer": {
"type": "custom",
"filter": [
"lowercase"
]
}
},
"filter": {
"german_stemmer": {
"type": "stemmer",
"language": "light_german"
},
"ngram_filter": {
"type": "shingle",
"max_shingle_size": 4,
"min_shingle_size": 2,
"output_unigrams": false,
"output_unigrams_if_no_shingles": false
}
},
"analyzer": {
"german": {
"tokenizer": "standard",
"filter": [
"lowercase",
"german_synonyms",
"german_stop",
"german_keywords",
"german_no_stemming",
"german_stemmer"
]
},
"german_ngram": {
"tokenizer": "standard",
"filter": [
"lowercase",
"german_synonyms",
"german_keywords",
"german_no_stemming",
"german_stemmer",
"ngram_filter"
]
}
}
}
},
"mappings": {
"properties": {
"description": {
"type": "text",
"copy_to": "searchableText",
"analyzer": "german"
},
"name": {
"type": "text",
"copy_to": "searchableText",
"analyzer": "german"
},
"userTags": {
"type": "keyword",
"copy_to": "searchableText",
"normalizer": "lowercase_normalizer"
},
"searchableText": {
"type": "text",
"analyzer": "german",
"fields": {
"ngram": {
"type": "text",
"analyzer": "german_ngram"
}
}
},
"searches": {
"type": "keyword",
"copy_to": "searchableText",
"normalizer": "lowercase_normalizer"
}
}
}
}
编辑 2: 这些是提到的过滤器:
"filter": {
"german_stop": {
"type": "stop",
"stopwords": "_german_"
},
"german_stemmer": {
"type": "stemmer",
"language": "light_german"
},
"ngram_filter": {
"type": "shingle",
"max_shingle_size": 4,
"min_shingle_size": 2,
"output_unigrams": false,
"output_unigrams_if_no_shingles": false
}
}
对于索引为“关键字”的字段,我通常更喜欢 QueryString 查询 DSL 而不是匹配查询。
例如:
{
"query" : {
"query_string" : {
"query" : "my_field:('hello', 'wonderful', 'world')"
}
}
}
将匹配您编写的所有那些应该匹配的组合,而不是您不想要的那些。括号中术语的关系类似于 SQL "IN",因此出现在该字段中的任何一个都将与文档匹配。此外,这种格式为您创建复杂搜索提供了极大的灵活性。如果这有帮助,请告诉我。
我尝试使用您的设置和映射创建索引,但由于未提供以下过滤器,删除这些过滤器后出现错误并创建了索引。
"german_synonyms",
"german_stop",
"german_keywords",
"german_no_stemming",
在那之后,我索引了您的示例文档 hello wonderful world
并使用了您的搜索查询,但它按您的预期工作正常并且没有 return hell
或 hello fniefsgbsugbs
如下图
{
"size": 100,
"query": {
"bool": {
"filter": [
{
"match": {
"searchableText": {
"query": "hello fniefsgbsugbs",
"operator": "AND",
"fuzziness": "0",
"prefix_length": 0,
"max_expansions": 50,
"minimum_should_match": "100%",
"fuzzy_transpositions": false,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": false,
"boost": 1
}
}
}
]
}
}
}
它 returns
"hits": {
"total": {
"value": 0,
"relation": "eq"
},
"max_score": null,
"hits": []
}
答案与 hell
相同,而它 return 的结果与 hello
、hello wonderful
和其他预期匹配的术语。
编辑: 您正在使用已分析的 match query 即,它分析搜索词,应用在字段上应用索引时间的同一分析器,并且将搜索时间标记与索引时间标记相匹配。
为了正确调试此类问题,请使用 analyze API 并检查您的索引文档标记和搜索词标记。
我想使用 ElasticSearch Java API 创建一个查询,它只匹配 (1) 完整的单词和 (2) 来自搜索查询的所有单词。这是一个例子:
正文:
hello wonderful world
这些应该匹配:
hello
hello wonderful
hello world
wonderful world
hello wonderful world
wonderful
world
这些不应该匹配:
hell
hello fniefsgbsugbs
我尝试了以下参数进行匹配查询,但它仍然与上面的两个示例匹配。
这是使用 ElasticSearch 7.7.1 生成查询的代码 Java API:
import org.elasticsearch.index.query.QueryBuilders
...
QueryBuilders.matchQuery(field, query)
.autoGenerateSynonymsPhraseQuery(false)
.fuzziness(0)
.prefixLength(0)
.fuzzyTranspositions(false)
.operator(Operator.AND)
.minimumShouldMatch("100%")
这将生成此查询:
{
"size": 100,
"query": {
"bool": {
"filter": [
{
"match": {
"searchableText": {
"query": "hell",
"operator": "AND",
"fuzziness": "0",
"prefix_length": 0,
"max_expansions": 50,
"minimum_should_match": "100%",
"fuzzy_transpositions": false,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": false,
"boost": 1
}
}
}
]
}
}
}
有人可以帮我找到一个好的解决方案吗?
编辑: 以下是设置和映射(我删除了与 searchableText
无关的所有内容以使其尽可能小):
{
"settings": {
"analysis": {
"normalizer": {
"lowercase_normalizer": {
"type": "custom",
"filter": [
"lowercase"
]
}
},
"filter": {
"german_stemmer": {
"type": "stemmer",
"language": "light_german"
},
"ngram_filter": {
"type": "shingle",
"max_shingle_size": 4,
"min_shingle_size": 2,
"output_unigrams": false,
"output_unigrams_if_no_shingles": false
}
},
"analyzer": {
"german": {
"tokenizer": "standard",
"filter": [
"lowercase",
"german_synonyms",
"german_stop",
"german_keywords",
"german_no_stemming",
"german_stemmer"
]
},
"german_ngram": {
"tokenizer": "standard",
"filter": [
"lowercase",
"german_synonyms",
"german_keywords",
"german_no_stemming",
"german_stemmer",
"ngram_filter"
]
}
}
}
},
"mappings": {
"properties": {
"description": {
"type": "text",
"copy_to": "searchableText",
"analyzer": "german"
},
"name": {
"type": "text",
"copy_to": "searchableText",
"analyzer": "german"
},
"userTags": {
"type": "keyword",
"copy_to": "searchableText",
"normalizer": "lowercase_normalizer"
},
"searchableText": {
"type": "text",
"analyzer": "german",
"fields": {
"ngram": {
"type": "text",
"analyzer": "german_ngram"
}
}
},
"searches": {
"type": "keyword",
"copy_to": "searchableText",
"normalizer": "lowercase_normalizer"
}
}
}
}
编辑 2: 这些是提到的过滤器:
"filter": {
"german_stop": {
"type": "stop",
"stopwords": "_german_"
},
"german_stemmer": {
"type": "stemmer",
"language": "light_german"
},
"ngram_filter": {
"type": "shingle",
"max_shingle_size": 4,
"min_shingle_size": 2,
"output_unigrams": false,
"output_unigrams_if_no_shingles": false
}
}
对于索引为“关键字”的字段,我通常更喜欢 QueryString 查询 DSL 而不是匹配查询。 例如:
{
"query" : {
"query_string" : {
"query" : "my_field:('hello', 'wonderful', 'world')"
}
}
}
将匹配您编写的所有那些应该匹配的组合,而不是您不想要的那些。括号中术语的关系类似于 SQL "IN",因此出现在该字段中的任何一个都将与文档匹配。此外,这种格式为您创建复杂搜索提供了极大的灵活性。如果这有帮助,请告诉我。
我尝试使用您的设置和映射创建索引,但由于未提供以下过滤器,删除这些过滤器后出现错误并创建了索引。
"german_synonyms",
"german_stop",
"german_keywords",
"german_no_stemming",
在那之后,我索引了您的示例文档 hello wonderful world
并使用了您的搜索查询,但它按您的预期工作正常并且没有 return hell
或 hello fniefsgbsugbs
如下图
{
"size": 100,
"query": {
"bool": {
"filter": [
{
"match": {
"searchableText": {
"query": "hello fniefsgbsugbs",
"operator": "AND",
"fuzziness": "0",
"prefix_length": 0,
"max_expansions": 50,
"minimum_should_match": "100%",
"fuzzy_transpositions": false,
"lenient": false,
"zero_terms_query": "NONE",
"auto_generate_synonyms_phrase_query": false,
"boost": 1
}
}
}
]
}
}
}
它 returns
"hits": {
"total": {
"value": 0,
"relation": "eq"
},
"max_score": null,
"hits": []
}
答案与 hell
相同,而它 return 的结果与 hello
、hello wonderful
和其他预期匹配的术语。
编辑: 您正在使用已分析的 match query 即,它分析搜索词,应用在字段上应用索引时间的同一分析器,并且将搜索时间标记与索引时间标记相匹配。
为了正确调试此类问题,请使用 analyze API 并检查您的索引文档标记和搜索词标记。