Одинаковая агрегация по нескольким метрикам

Я настроил снегоочиститель с Elasticsearch.

Когда я хочу получить данные, я просто делаю обычные запросы и использую агрегаты, чтобы получить их по дням, странам и т. Д.

Итак, я хочу выяснить рейтинг кликов для этих агрегатов, у меня есть 2 вида событий: просмотры страниц и клики.

В настоящее время я делаю 2 запроса:

Просмотры страниц:

{
    "size": 0,
    "query": {
        "filtered": {
            "filter": {
                "bool": {
                    "must": [
                        {
                            "term": {
                                "event": "page_view"
                            }
                        }
                    ],
                    "must_not": {
                        "term": {
                            "br_family": "Robot"
                        }
                    }
                }
            }
        }
    },
    "aggs": {
        "dates": {
            "date_histogram": {
                "field": "collector_tstamp",
                "interval": "day"
            }
        }
    }
}

Просмотры:

{
    "size": 0,
    "query": {
        "filtered": {
            "filter": {
                "bool": {
                    "must": [
                        {
                            "term": {
                                "event": "struct"
                            }
                        },
                        {
                            "term": {
                                "se_action": "click"
                            }
                        }
                    ],
                    "must_not": {
                        "term": {
                            "br_family": "Robot"
                        }
                    }
                }
            }
        }
    },
    "aggs": {
        "dates": {
            "date_histogram": {
                "field": "collector_tstamp",
                "interval": "day"
            }
        }
    }
}

Я форматирую ответ на что-то более простое в использовании, а затем объединяю их в PHP, используя что-то вроде этого.

function merge_metrics($pv,$c){
    $r = array();

    if(count($pv) > 0){
        foreach ($pv as $key => $value) {
            $r[$value['name']]['page_views'] += $value['count']; 
        }
    }
    if(count($c) > 0){
        foreach ($c as $key => $value) {
            $r[$value['name']]['clicks'] += $value['count']; 
        }
    }

    $rf = array();

    foreach ($r as $key => $value) {
        $tmp_clicks = isset($value['clicks']) ? $value['clicks'] : 0;
        $tmp_page_views = isset($value['page_views']) ? isset($value['page_views']) : 0;
        $rf[] = array(
                'name' => $key,
                'page_views' => $tmp_page_views,
                'clicks' => $tmp_clicks,
                'ctr' => ctr($tmp_clicks,$tmp_page_views)
            ); 
    }

    return $rf;
}

И $ pv, и $ c являются массивами, которые содержат агрегаты, полученные в результате запросов к Elasticsearch, и я делаю некоторое форматирование для простоты использования.

Мой вопрос:

Можно ли получить несколько метрик (в моем случае просмотров страниц и кликов, это особые фильтры) и выполнять одинаковые агрегации для обоих? затем возвращает агрегации что-то вроде:

{
    "data": [
        {
            "day": "2015-10-13",
            "page_views": 61,
            "clicks": 0,
        },
        {
            "day": "2015-10-14",
            "page_views": 135,
            "clicks": 1,
        },
        {
            "day": "2015-10-15",
            "page_views": 39,
            "clicks": 0,
        }
    ]
}

Но без меня, чтобы вручную объединить их?

1 ответ

Решение

Да, это определенно возможно, если вы объедините свои агрегаты в один запрос. Например, я полагаю, у вас есть один запрос для просмотра страниц:

{
    "query": {...}
    "aggregations": {
        "by_day": {
            "date_histogram": {
                "field": "day",
                "interval": "day"
            },
            "aggs": {
                "page_views_per_day": {
                    "sum": {
                        "field": "page_views"
                    }
                }
            }
        }
    }
}

И еще один запрос на клики:

{
    "query": {...}
    "aggregations": {
        "by_day": {
            "date_histogram": {
                "field": "day",
                "interval": "day"
            },
            "aggs": {
                "clicks_per_day": {
                    "sum": {
                        "field": "clicks"
                    }
                }
            }
        }
    }
}

Если у вас есть те же ограничения в вашем queryвы можете объединить их вместе на date_histogram уровень, как это:

{
    "query": {...}
    "aggregations": {
        "by_day": {
            "date_histogram": {
                "field": "day",
                "interval": "day"
            },
            "aggs": {
                "page_views_per_day": {
                    "sum": {
                        "field": "page_views"
                    }
                },
                "clicks_per_day": {
                    "sum": {
                        "field": "clicks"
                    }
                }
            }
        }
    }
}

ОБНОВИТЬ

Поскольку ваши запросы различны для каждого из ваших агрегатов, мы должны сделать это немного по-другому, то есть с помощью дополнительного filters агрегация, как это:

{
  "size": 0,
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "terms": {
                "event": [
                  "page_view",
                  "struct"
                ]
              }
            }
          ],
          "should": {
            "term": {
              "se_action": "click"
            }
          },
          "must_not": {
            "term": {
              "br_family": "Robot"
            }
          }
        }
      }
    }
  },
  "aggs": {
    "dates": {
      "date_histogram": {
        "field": "collector_tstamp",
        "interval": "day"
      },
      "aggs": {
        "my_filters": {
          "filters": {
            "filters": {
              "page_views_filter": {
                "bool": {
                  "must": [
                    {
                      "term": {
                        "event": "page_view"
                      }
                    }
                  ],
                  "must_not": {
                    "term": {
                      "br_family": "Robot"
                    }
                  }
                }
              },
              "clicks_filter": {
                "bool": {
                  "must": [
                    {
                      "term": {
                        "event": "struct"
                      }
                    },
                    {
                      "term": {
                        "se_action": "click"
                      }
                    }
                  ],
                  "must_not": {
                    "term": {
                      "br_family": "Robot"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Теперь для каждого ежедневного сегмента вы получите два вложенных сегмента: один для количества просмотров страниц, а другой для количества кликов.

Другие вопросы по тегам