【问题标题】:Elastic Search- Fetch Distinct Tags弹性搜索 - 获取不同的标签
【发布时间】:2015-02-04 04:07:06
【问题描述】:

我有以下格式的文件:

{
 _id :"1",
  tags:["guava","apple","mango", "banana", "gulmohar"]
}


{
  _id:"2",
  tags: ["orange","guava", "mango shakes", "apple pie", "grammar"]
}

{

  _id:"3",
  tags: ["apple","grapes", "water", "gulmohar","water-melon", "green"]
}

现在,我想从以前缀g* 开头的整个文档“标签字段”中获取唯一标签值,以便标签建议器显示这些唯一标签(以 Stackoverflow 站点为例)。

例如:每当用户键入“g”时: "guava", "gulmohar", "grammar", "grapes" and "green" 应该作为结果返回。 IE。查询应该返回带有前缀 g* 的不同标签。

我到处都试过了,浏览了整个文档,搜索了 es 论坛,但我没有找到任何线索,这让我很沮丧。

我尝试了聚合,但聚合返回标签字段中整个单词/标记的不同计数。它不返回以“g”开头的唯一标签列表。

"query": {
    "filtered": {
      "query": {
        "bool": {
          "should": [
            {
              "query_string": {
                "allow_leading_wildcard": false,
                "fields": [
                  "tags"
                ],
                "query": "g*",
                "fuzziness":0
              }
            }
          ]
        }
      },
      "filter": {
         //some condition on other  field...
      }

    }

  },
  "aggs": {
    "distinct_tags": {
      "terms": {
        "field": "tags",
        "size": 10
      }
    }
  }, 

以上结果:guava(w), apple(q), mango(1),...

有人可以建议我获取所有带有前缀 input_prefix* 的不同标签的正确方法吗?

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    这有点像 hack,但这似乎可以完成你想要的。

    我创建了一个索引并添加了您的文档:

    DELETE /test_index
    
    PUT /test_index
    {
       "settings": {
          "number_of_shards": 1,
          "number_of_replicas": 0
       }
    }
    
    POST /test_index/_bulk
    {"index":{"_index":"test_index","_type":"doc","_id":1}}
    {"tags":["guava","apple","mango", "banana", "gulmohar"]}
    {"index":{"_index":"test_index","_type":"doc","_id":2}}
    {"tags": ["orange","guava", "mango shakes", "apple pie", "grammar"]}
    {"index":{"_index":"test_index","_type":"doc","_id":3}}
    {"tags": ["guava","apple","grapes", "water", "grammar","gulmohar","water-melon", "green"]}
    

    然后我使用prefix queryhighlighting的组合如下:

    POST /test_index/_search
    {
       "query": {
          "prefix": {
             "tags": {
                "value": "g"
             }
          }
       },
       "fields": [ ], 
       "highlight": {
           "pre_tags": [""],
           "post_tags": [""], 
           "fields": {
               "tags": {}
           }
       }
    }
    ...
    {
       "took": 5,
       "timed_out": false,
       "_shards": {
          "total": 1,
          "successful": 1,
          "failed": 0
       },
       "hits": {
          "total": 3,
          "max_score": 1,
          "hits": [
             {
                "_index": "test_index",
                "_type": "doc",
                "_id": "1",
                "_score": 1,
                "highlight": {
                   "tags": [
                      "guava",
                      "gulmohar"
                   ]
                }
             },
             {
                "_index": "test_index",
                "_type": "doc",
                "_id": "2",
                "_score": 1,
                "highlight": {
                   "tags": [
                      "guava",
                      "grammar"
                   ]
                }
             },
             {
                "_index": "test_index",
                "_type": "doc",
                "_id": "3",
                "_score": 1,
                "highlight": {
                   "tags": [
                      "guava",
                      "grapes",
                      "grammar",
                      "gulmohar",
                      "green"
                   ]
                }
             }
          ]
       }
    }
    

    这是我使用的代码: http://sense.qbox.io/gist/c14675ee8bd3934389a6cb0c85ff57621a17bf11

    当然,您尝试执行的操作相当于自动完成,并且可能有比我上面发布的更好的方法(尽管它们涉及更多)。以下是我们撰写的几篇关于设置自动完成功能的博文:

    http://blog.qbox.io/quick-and-dirty-autocomplete-with-elasticsearch-completion-suggest

    http://blog.qbox.io/multi-field-partial-word-autocomplete-in-elasticsearch-using-ngrams

    【讨论】:

    • 谢谢。但这不是预期的结果。这并没有给出跨整个文档标签字段的唯一标签列表。在这里,我需要一个一个地扫描所有的命中,并且必须将每个标签条目放在一个类似数据结构的 hashmap 中,不是吗? "tags": [ "guava", "gulmohar" ],` "tags": [ "guava", "grammar" ], "tags": [ "guava", "grapes", "grammar", "gulmohar", "green" ]`
    • 通过您的实现,我需要扫描每个命中中的每个条目并将它们中的每一个保存在哈希图中。我认为,第三个文档造成了一些混乱,因此编辑了有问题的示例,使其更加清晰。
    • 老实说,我认为没有办法完全按照您的要求进行操作。您可能必须编写一点点处理代码才能获得您正在寻找的结果结构。 Elasticsearch 将完成繁重的工作,但您可能必须编写一个 for 循环来处理结果。或者,您可以更改数据结构,使每个文档只有一个标签。然后将文档过滤到与前缀匹配的文档非常容易。不过,您仍然需要编写一个 for 循环来处理命中。
    • 当然,我发布的两个链接解释了设置自动完成的几种不同方法。不过,两者都需要更改数据结构。一切都是取舍。
    • 我能够通过遵循您的建议和您的回答中提到的两个博客文章链接来实现目标。接受您的建议的答案就像魅力一样,您向我展示了正确的方向。
    【解决方案2】:

    根据@Sloan Ahrens 的建议,我做了以下操作:

    更新了映射:

      "tags": {
          "type": "completion",
          "context": {
            "filter_color": {
              "type": "category",
              "default": "",
              "path": "fruits.color"
            },
            "filter_type": {
              "type": "category",
              "default": "",
              "path": "fruits.type"
            }
          }
       }
    

    参考:ES API Guide

    插入了这些索引:

    {
     _id :"1",
      tags:{input" :["guava","apple","mango", "banana", "gulmohar"]},
      fruits:{color:'bar',type:'alice'}
    }
    
    
    {
      _id:"2",
       tags:{["orange","guava", "mango shakes", "apple pie", "grammar"]}
       fruits:{color:'foo',type:'bob'}
    }
    
    {
    
      _id:"3",
      tags:{ ["apple","grapes", "water", "gulmohar","water-melon", "green"]}
      fruits:{color:'foo',type:'alice'}
    }
    

    我不需要修改太多,我的原始索引。刚刚在标签数组之前添加了input

    POST rescu1/_suggest?pretty'
    {
      "suggest": {
        "text": "g",
        "completion": {
          "field": "tags",
          "size": 10,
          "context": {
            "filter_color": "bar",
            "filter_type": "alice"
          }
        }
      }
    }
    

    给了我想要的输出。

    我接受了@Sloan Ahrens 的回答,因为他的建议对我来说就像是一种魅力,他向我展示了正确的方向。

    【讨论】:

      猜你喜欢
      • 2021-03-08
      • 2015-12-26
      • 1970-01-01
      • 2016-02-13
      • 1970-01-01
      • 2017-01-04
      • 1970-01-01
      • 2016-03-28
      • 1970-01-01
      相关资源
      最近更新 更多