首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >匹配查询中的所有准确单词

匹配查询中的所有准确单词
EN

Stack Overflow用户
提问于 2020-11-17 15:15:47
回答 2查看 301关注 0票数 0

我希望使用ElasticSearch Java创建一个查询,该查询只匹配(1)完整单词和(2)搜索查询中的所有单词。以下是一个例子:

文本:

hello wonderful world

这些应符合:

代码语言:javascript
复制
hello
hello wonderful
hello world
wonderful world
hello wonderful world
wonderful
world

这些不应该匹配:

  1. hell
  2. hello fniefsgbsugbs

为了进行匹配查询,我尝试了以下参数,但它仍然与上面的两个示例匹配。

这是使用ElasticSearch 7.7.1JavaAPI生成查询的代码:

代码语言:javascript
复制
import org.elasticsearch.index.query.QueryBuilders
...

QueryBuilders.matchQuery(field, query)
            .autoGenerateSynonymsPhraseQuery(false)
            .fuzziness(0)
            .prefixLength(0)
            .fuzzyTranspositions(false)
            .operator(Operator.AND)
            .minimumShouldMatch("100%")

它将生成以下查询:

代码语言:javascript
复制
{
  "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无关的内容,以使其尽可能最小化):

代码语言:javascript
复制
{
    "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: --这些是提到的过滤器:

代码语言:javascript
复制
"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
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-11-18 08:16:24

我尝试用您的设置和映射创建索引,但是由于没有提供以下过滤器,所以在删除这些过滤器后,我得到了错误并创建了索引。

代码语言:javascript
复制
"german_synonyms",
"german_stop",
"german_keywords",
"german_no_stemming",

之后,我对您的示例文档hello wonderful world进行了索引,并使用了您的搜索查询,但是它运行得很好,与您预期的一样,并且没有返回hellhello fniefsgbsugbs的结果,如下所示

代码语言:javascript
复制
{
    "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
                        }
                    }
                }
            ]
        }
    }
}

然后它又回来了

代码语言:javascript
复制
"hits": {
        "total": {
            "value": 0,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    }

Ans在hell中也是如此,而返回结果时使用hellohello wonderful和其他预期匹配的术语。

编辑:您使用的是被分析的匹配查询,它分析搜索项,使用相同的分析器在字段上应用索引时间,并将搜索时间标记与索引时间标记匹配。

为了正确地调试这些问题,请使用 分析API 检查索引文档标记和搜索术语标记.

票数 1
EN

Stack Overflow用户

发布于 2020-11-18 08:08:51

对于索引为“关键字”的字段,比起匹配查询,我更喜欢QueryString查询DSL。例如:

代码语言:javascript
复制
{
    "query" : {
        "query_string" : {
            "query" : "my_field:('hello', 'wonderful', 'world')"
        }
    }
}

将匹配所有你写的组合应该匹配,而不是你不想要的。括号中的术语之间的关系类似于SQL " in ",因此字段中出现的任何术语都将与文档匹配。此外,这种格式使您在创建复杂搜索时具有很大的灵活性。如果这有帮助的话请告诉我。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64878011

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档