如何获得具有多个字段的 Elasticsearch 聚合

Posted

技术标签:

【中文标题】如何获得具有多个字段的 Elasticsearch 聚合【英文标题】:How to get an Elasticsearch aggregation with multiple fields 【发布时间】:2015-08-24 01:36:21 【问题描述】:

我正在尝试查找与当前正在查看的标签相关的标签。我们索引中的每个文档都被标记。每个标签由两部分组成 - 一个 ID 和文本名称:


    ...
    meta: 
        ...
        tags: [
            
                id: 123,
                name: 'Biscuits'
            ,
            
                id: 456,
                name: 'Cakes'
            ,
            
                id: 789,
                name: 'Breads'
            
        ]
    

要获取相关标签,我只是查询文档并获取它们的标签聚合:


    "query": 
        "bool": 
            "must": [
                
                    "match": 
                        "item.meta.tags.id": "123"
                    
                ,
                
                    ...
                
            ]
        
    ,
    "aggs": 
        "baked_goods": 
            "terms": 
                "field": "item.meta.tags.id",
                "min_doc_count": 2
            
        
    

这非常有效,我得到了我想要的结果。但是,我需要标签 ID 名称来做任何有用的事情。我已经探索了如何做到这一点,解决方案似乎是:

    索引时合并字段 将字段组合在一起的脚本 嵌套聚合

选项一和二对我来说不可用,所以我一直选择 3,但它没有以预期的方式响应。给定以下查询(仍在搜索也标记为“饼干”的文档):


    ...
    "aggs": 
        "baked_goods": 
            "terms": 
                "field": "item.meta.tags.id",
                "min_doc_count": 2
            ,
            "aggs": 
                "name": 
                    "terms": 
                        "field": "item.meta.tags.name"
                    
                
            
        
    

我会得到这个结果:


    ...
    "aggregations": 
        "baked_goods": 
            "buckets": [
                
                    "key": "456",
                    "doc_count": 11,
                    "name": 
                        "buckets": [
                            
                                "key": "Biscuits",
                                "doc_count": 11
                            ,
                            
                                "key": "Cakes",
                                "doc_count": 11
                            
                        ]
                    
                
            ]
        
    

嵌套聚合包括搜索词我所追求的标签(按字母顺序返回)。

我试图通过在嵌套聚合中添加 exclude 来缓解这种情况,但这会使查询速度减慢太多(对于 500000 个文档,大约是 100 倍)。到目前为止,最快的解决方案是手动对结果进行重复数据删除。

在响应中获取包含标签 ID 和标签名称的标签聚合的最佳方法是什么?

感谢您到此为止!

【问题讨论】:

【参考方案1】:

从外观上看,您的tags 不是nested。 要使此聚合起作用,请使用you need it nested,以便idname 之间存在关联。没有nestedids 的列表只是一个数组,names 的列表是另一个数组:

    "item": 
      "properties": 
        "meta": 
          "properties": 
            "tags": 
              "type": "nested",           <-- nested field
              "include_in_parent": true,  <-- to, also, keep the flat array-like structure
              "properties": 
                "id": 
                  "type": "integer"
                ,
                "name": 
                  "type": "string"
                
              
            
          
        
      
    

另外,请注意,我已将这一行 "include_in_parent": true 添加到映射中,这意味着您的 nested 标记也将表现得像一个“平面”类数组结构。

因此,到目前为止,您在查询中的所有内容仍然可以正常工作,而无需对查询进行任何更改。

但是,对于您的这个特定查询,聚合需要更改为以下内容:


  "aggs": 
    "baked_goods": 
      "nested": 
        "path": "item.meta.tags"
      ,
      "aggs": 
        "name": 
          "terms": 
            "field": "item.meta.tags.id"
          ,
          "aggs": 
            "name": 
              "terms": 
                "field": "item.meta.tags.name"
              
            
          
        
      
    
  

结果是这样的:

   "aggregations": 
      "baked_goods": 
         "doc_count": 9,
         "name": 
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
               
                  "key": 123,
                  "doc_count": 3,
                  "name": 
                     "doc_count_error_upper_bound": 0,
                     "sum_other_doc_count": 0,
                     "buckets": [
                        
                           "key": "biscuits",
                           "doc_count": 3
                        
                     ]
                  
               ,
               
                  "key": 456,
                  "doc_count": 2,
                  "name": 
                     "doc_count_error_upper_bound": 0,
                     "sum_other_doc_count": 0,
                     "buckets": [
                        
                           "key": "cakes",
                           "doc_count": 2
                        
                     ]
                  
               ,
               .....

【讨论】:

@i_like_robots 我很好奇,你测试过我建议的解决方案了吗? 他决定把赏金留给自己,谢谢你的好回答! 最后,是的!我们最终能够花时间创建一个具有正确嵌套字段的新索引,但恐怕直到最近才出现。感谢您抽出宝贵时间回答我的问题,对于忽略任何 Stack Overflow 礼仪,我深表歉意! 现在不推荐使用“字符串”字段。检查elastic.co/guide/en/elasticsearch/reference/current/… 是否使用文本/关键字组合字段。

以上是关于如何获得具有多个字段的 Elasticsearch 聚合的主要内容,如果未能解决你的问题,请参考以下文章

ElasticSearch 按多个字段分组

MongoDB - 具有多个字段并获得最新结果

如何在elasticsearch中使多个字段可搜索[关闭]

如何设置具有多个实体绑定的 ElasticSearch 索引结构

跨文档的Elasticsearch查询数组字段

json Elasticsearch获得某些字段的最大值