【问题标题】:Elasticsearch: query for multiple words across multiple fields (with prefix)Elasticsearch:跨多个字段查询多个单词(带前缀)
【发布时间】:2019-01-28 04:47:47
【问题描述】:

我正在尝试实现由 ES 索引提供支持的自动建议控件。索引有多个字段,我希望能够使用 AND 运算符跨多个字段进行查询并允许部分匹配(仅限前缀)。

举个例子,假设我有 2 个要查询的字段:“颜色”和“动物”。 我希望能够完成诸如“duc”、“duck”、“purpl”、“purple”、“purple duck”之类的查询。 我设法使用带有 AND 运算符的 multi_match() 来完成所有这些工作。

我似乎无法匹配“purple duc”之类的查询,因为 multi_match 不允许使用通配符。

我查看了 match_phrase_prefix(),但据我了解,它不会跨越多个字段。

我正在转向实现标记器:感觉解决方案可能就在那里,所以最终的问题是:

1) 有人可以确认没有开箱即用的功能可以做我想做的事吗?这感觉像是一种足够常见的模式,可以随时使用。

2) 有人可以提出任何解决方案吗?标记器是解决方案的一部分吗? 我很高兴被指出正确的方向并自己做更多的研究。 显然,如果有人有可行的解决方案可以分享,那就太棒了。

提前致谢 - F

【问题讨论】:

    标签: elasticsearch autocomplete autosuggest


    【解决方案1】:

    实际上,我不久前为Qbox 写了一篇关于此的博客文章,您可以在此处找到:http://blog.qbox.io/multi-field-partial-word-autocomplete-in-elasticsearch-using-ngrams。 (不幸的是,帖子中的某些链接已损坏,目前无法轻松修复,但希望您能明白这一点。)

    我将向您推荐该帖子以了解详细信息,但这里有一些代码可用于快速测试它。请注意,我使用的是edge ngrams,而不是完整的ngrams

    还要特别注意_all fieldmatch query operator的使用。

    好的,下面是映射:

    PUT /test_index
    {
       "settings": {
          "analysis": {
             "filter": {
                "edgeNGram_filter": {
                   "type": "edgeNGram",
                   "min_gram": 2,
                   "max_gram": 20
                }
             },
             "analyzer": {
                "edgeNGram_analyzer": {
                   "type": "custom",
                   "tokenizer": "whitespace",
                   "filter": [
                      "lowercase",
                      "asciifolding",
                      "edgeNGram_filter"
                   ]
                }
             }
          }
       },
       "mappings": {
          "doc": {
             "_all": {
                "enabled": true,
                "index_analyzer": "edgeNGram_analyzer",
                "search_analyzer": "standard"
             },
             "properties": {
                "field1": {
                   "type": "string",
                   "include_in_all": true
                },
                "field2": {
                   "type": "string",
                   "include_in_all": true
                }
             }
          }
       }
    }
    

    现在添加一些文档:

    POST /test_index/doc/_bulk
    {"index":{"_id":1}}
    {"field1":"purple duck","field2":"brown fox"}
    {"index":{"_id":2}}
    {"field1":"slow purple duck","field2":"quick brown fox"}
    {"index":{"_id":3}}
    {"field1":"red turtle","field2":"quick rabbit"}
    

    这个查询似乎说明了你想要什么:

    POST /test_index/_search
    {
       "query": {
          "match": {
             "_all": {
                 "query": "purp fo slo",
                 "operator": "and"
             }
          }
       }
    }
    

    返回:

    {
       "took": 5,
       "timed_out": false,
       "_shards": {
          "total": 5,
          "successful": 5,
          "failed": 0
       },
       "hits": {
          "total": 1,
          "max_score": 0.19930676,
          "hits": [
             {
                "_index": "test_index",
                "_type": "doc",
                "_id": "2",
                "_score": 0.19930676,
                "_source": {
                   "field1": "slow purple duck",
                   "field2": "quick brown fox"
                }
             }
          ]
       }
    }
    

    这是我用来测试它的代码:

    http://sense.qbox.io/gist/b87e426062f453d946d643c7fa3d5480cd8e26ec

    【讨论】:

    • 这正是我所需要的。太棒了
    • 我也是!好东西
    • @SloanAhrens 在您的博客文章中,您使用了实际上不可用的过滤器的标记字符。标记字符仅可用于标记器而不是过滤器。那么我们该如何解决呢?
    • 如何使用包含电子邮件地址的字段? @ 似乎打破了它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-15
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 2022-06-29
    • 1970-01-01
    相关资源
    最近更新 更多