【问题标题】:Combine results of multiple aggregations合并多个聚合的结果
【发布时间】:2020-08-20 05:00:23
【问题描述】:

我有movies 索引,其中每个文档都有这样的结构:

文件:

{
                    "color": "Color",
                    "director_name": "Sam Raimi",
                    "actor_2_name": "James Franco",
                    "movie_title": "Spider-Man 2",
                    "actor_3_name" : "Brad Pitt",
                    "actor_1_name": "J.K. Simmons"
}

我需要计算每个演员对应的电影数量(演员可以在 actor_1_name 或 actor_2_name 或 actor_3_name 字段中)

这3个字段的映射是:

映射

"mappings": {
            "properties": {
                "actor_1_name": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "actor_2_name": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                 "actor_3_name": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            }
       }
}

有没有一种方法可以聚合结果,它可以组合来自所有 3 个参与者字段的术语并给出单个聚合。

目前我正在为每个参与者字段创建单独的聚合,并通过我的 JAVA 代码将这些不同的聚合合并为一个。

通过创建不同的聚合来搜索查询:

搜索查询:

{
    "aggs" : {
        "actor1_count" : {
            "terms" : {
                "field" : "actor_1_name.keyword"
            }
        },
        "actor2_count" : {
            "terms" : {
                "field" : "actor_2_name.keyword"
            }
        },
        "actor3_count" : {
            "terms" : {
                "field" : "actor_3_name.keyword"
            }
        }
    }
}

结果

示例结果是:

"aggregations": {
"actor1_count": {

            "buckets": [

                {
                    "key": "Johnny Depp",
                    "doc_count": 2
                }
            ]
},

"actor2_count": {

            "buckets": [
                {
                    "key": "Johnny Depp",
                    "doc_count": 1                   }
      ]
},
"actor3_count": {

            "buckets": [

                {
                    "key": "Johnny Depp",
                    "doc_count": 3
                }

           ]
    }
 }

那么,我可以通过 Elasticsearch 将所有 3 个聚合的结果合并到一个聚合中,而不是创建不同的聚合。

基本上这是我想要的:

"aggregations": {
    "actor_count": {

                "buckets": [

                    {
                        "key": "Johnny Depp",
                        "doc_count": 6
                    }
                ]
    }
}

Johnny Depp doc_count 应该显示所有 3 个字段 actor_1_name、actor_2_name、actor_3_name 的总和,无论它出现在哪里)

我已经尝试过脚本,但它运行正常。

脚本查询:

{
    "aggregations": {
        "name": {
            "terms": {
                "script": "doc['actor_1_name.keyword'].value + ' ' +  doc['actor_2_name.keyword'].value + ' ' + doc['actor_2_name.keyword'].value"
            }
        }
    }
}

它是结合演员的名字,然后给出结果。

结果:

"buckets": [

                {
                    "key": "Steve Buscemi Adam Sandler Adam Sandler",
                    "doc_count": 6
                },
                {
                    "key": "Leonard Nimoy Nichelle Nichols Nichelle Nichols",
                    "doc_count": 4
                }

            ]

【问题讨论】:

    标签: elasticsearch elasticsearch-aggregation elasticsearch-query


    【解决方案1】:

    这对terms 不起作用。我认为必须求助于scripted_metric

    GET actors/_search
    {
      "size": 0,
      "aggs": {
        "merged_actors": {
          "scripted_metric": {
            "init_script": "state.actors_map=[:]",
            "map_script": """
              def actor_keys = ['actor_1_name', 'actor_2_name', 'actor_3_name'];
    
              for (def key : actor_keys) {
    
                def actor_name = doc[key + '.keyword'].value;
    
                if (state.actors_map.containsKey(actor_name)) {
                  state.actors_map[actor_name] += 1;
                } else {
                  state.actors_map[actor_name] = 1; 
                }
              }
            """,
            "combine_script": "return state",
            "reduce_script": "return states"
          }
        }
      }
    }
    

    屈服

    ...
    "aggregations" : {
        "merged_actors" : {
          "value" : [
            {
              "actors_map" : {
                "Brad Pitt" : 5,
                "J.K. Simmons" : 1,
                "James Franco" : 3
              }
            }
          ]
        }
      }
    

    【讨论】:

    • 除了文档 'actor_1_name' 中的这类字段外,它还有像 'actor_1_facebook_likes' 之类的字段,它的类型为 Integer,sicnce 脚本也在尝试读取它。它抛出异常,因为该字段没有关键字字段。我能否具体提及我必须从哪个字段读取值。
    • 是的。我很担心,但我认为演员的数量很大。更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-07
    • 2014-01-25
    • 2014-02-23
    • 2016-07-31
    • 2019-01-30
    • 1970-01-01
    相关资源
    最近更新 更多