【问题标题】:Elasticsearch search bool + must queryElasticsearch search bool + 必须查询
【发布时间】:2018-12-03 14:17:50
【问题描述】:

谁能告诉我为什么这个 Elastic 查询会返回下面的结果。查询有 bool + must 部分,只有在字段 nn 中与字符串“softo”完全匹配时才应该匹配。查询如下:

"query":{
        "bool":{
            "must":[
                {"match":{"nn":"softo"}}
            ],
            "should":[
                {"match":{"nn":"sro"}},
                {"match":{"nn":"as"}},
                {"match":{"nn":"no"}},
                {"match":{"nn":"vos"}},
                {"match":{"nn":"ks"}}
            ]
        }
    }

它返回给我一个在 nn 字段中没有软的结果,例如:

            {
                "_index": "search_2",
                "_type": "doc",
                "_id": "17053188",
                "_score": 129.76167,
                "_source": {
                    "nn": "zo soz kovo zts nova as zts elektronika as",
                    "nazov": "ZO SOZ KOVO,ZŤS NOVA a.s.,ZTS ELEKTRONIKA a.s.",
                }
            },
            {
                "_index": "search_2",
                "_type": "doc",
                "_id": "45732078",
                "_score": 126.953285,
                "_source": {
                    "nn": "agentura socialnych sluzieb   ass no",
                    "nazov": "Agentúra sociálnych služieb - ASS n.o.",
                }
            }

我不明白。为什么它返回像“zo soz kovo zts nova as zts elektronika as”这样的结果,其中没有“softo”字符串。 nn 字段的映射如下所示:

{
    "search_2": {
        "aliases": {
            "search": {}
        },
        "mappings": {
            "doc": {
                "dynamic": "strict",
                "properties": { 
                    "nn": {
                        "type": "text",
                        "boost": 10,
                        "analyzer": "autocomplete"
                    }
                }
            }
        },
        "settings": {
            "index": {
                "refresh_interval": "-1",
                "number_of_shards": "4",
                "provided_name": "search_2",
                "creation_date": "1539693645683",
                "analysis": {
                    "filter": {
                        "synonym_filter": {
                            "ignore_case": "true",
                            "type": "synonym",
                            "synonyms_path": "synonyms/sk_SK.txt"
                        },
                        "lemmagen_filter_sk": {
                            "type": "lemmagen",
                            "lexicon": "sk"
                        },
                        "stopwords_SK": {
                            "ignore_case": "true",
                            "type": "stop",
                            "stopwords_path": "stopwords/slovak.txt"
                        },
                        "remove_duplicities": {
                            "type": "unique",
                            "only_on_same_position": "true"
                        },
                        "autocomplete_filter": {
                            "type": "edge_ngram",
                            "min_gram": "2",
                            "max_gram": "20"
                        }
                    },
                    "analyzer": {
                        "autocomplete": {
                            "filter": [
                                "stopwords_SK",
                                "lowercase",
                                "stopwords_SK",
                                "autocomplete_filter"
                            ],
                            "type": "custom",
                            "tokenizer": "standard"
                        },
                        "lower_ascii": {
                            "filter": [
                                "lowercase",
                                "asciifolding"
                            ],
                            "type": "custom",
                            "tokenizer": "standard"
                        },
                        "suggestion": {
                            "filter": [
                                "stopwords_SK",
                                "lowercase",
                                "stopwords_SK",
                                "asciifolding"
                            ],
                            "type": "custom",
                            "tokenizer": "standard"
                        }
                    }
                },
                "number_of_replicas": "1",
                "uuid": "eyxXza0pQxWeQCpXih8ngg",
                "version": {
                    "created": "6020399"
                }
            }
        }
    }
}

【问题讨论】:

  • 更糟糕的情况下,您可以让 ElasticSearch 找到 explain 匹配的内容

标签: elasticsearch search match


【解决方案1】:

你得到这些结果的原因是因为autocomplete 分析器应用于nn 字段。 我将根据以下字段进行解释:

"nn": "zo soz kovo zts nova as zts elektronika as"

为上述生成的令牌将是:

zo, so, soz, ko, kov, kovo, zt, zts, no, nov, nova, as, zt, zts, el, ele, elek, elekt, elektr, elektro, elektro, elektroni, elektronik, elektronika, as

现在匹配查询默认应用相同的分析器进行搜索,并且标记之间的默认运算符是 OR。所以{"match":{"nn":"softo"}} 实际上表现得像

{
  "match": {
    "nn": "so OR sof OR soft OR softo"
  }
}

正如您在 nn 字段中看到的那样,生成的令牌之一是 so,因此它得到了匹配。

【讨论】:

  • 最好的解释。非常感谢。
  • Elasticsearch 是否能够识别出“softo”令牌优于“so”令牌?
  • 如果您要问哪个更合适,那么是的。
【解决方案2】:
  1. 您可以在必须查询中将“match”更改为“term”。

    当调用“匹配”查询时,将计算该字段的分数。因此查询将回答“这个字符串匹配程度如何”的问题。

    当调用“term”查询时,不会计算分数。所以查询将回答简单的问题:是或否(匹配或不匹配)。


  1. 如果您确实需要全文搜索,您可以在“必须”查询中保留“匹配”并提高其分数。

    例如,如果你想将它的值提高 5,它看起来像这样:

    "must":[
        {"match": {"nn": {"boost": 5, "query": "softo"}}}
    ]
    

【讨论】:

  • 但是 term 只匹配字段 sting 的完全匹配。不使用对字符串进行标记的全文功能。我对吗?我需要使用匹配。可能是 should 子句应该有一个较小的权重。如何实现呢?
  • "term" 查询将找到与倒排索引生成的标记完全匹配(如果您查询的字段已分析)。当你使用“匹配”查询时,它会根据它与标记的匹配程度来计算分数。
猜你喜欢
  • 1970-01-01
  • 2015-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-15
  • 1970-01-01
相关资源
最近更新 更多