合并多个聚合的结果

Combine results of multiple aggregations

我有 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
                }

            ]

这不适用于 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
          }
        }
      ]
    }
  }