qnixdev
@qnixdev
Junior+ PHP Developer

Как оптимизировать следующий поисковый запрос в Elasticsearch?

Есть следующий запрос с ежедневной выборкой:
request

{
    "query": {
        "bool": {
            "filter": [
                {
                    "range": {
                        "created-at-date": {
                            "format": "yyyy-MM-dd",
                            "gte": "now-1M",
                            "lte": "now"
                        }
                    }
                }, {
                    "terms": {
                        "some-id": [1, 2, 3, 4]
                    }
                }
            ]
        }
    },
    "size": 0,
    "aggs": {
        "agg-date": {
            "date_histogram": {
                "field": "created-at-date",
                "calendar_interval": "1d",
                "min_doc_count": 0,
                "format": "yyyy-MM-dd",
                "extended_bounds": {
                    "min": "now-1M",
                    "max": "now"
                }
            },
            "aggs": {
                "country-agg": {
                    "terms": {
                        "field": "country.keyword"
                    }
                }
            }
        }
    }
}



в ответ получаю следующий ответ:
response

{
    "aggregations": {
        "agg-date": {
            "buckets": [
                {
                    "key_as_string": "2021-10-14",
                    "key": 1634169600000,
                    "doc_count": 255874,
                    "country-agg": {
                        "doc_count_error_upper_bound": 0,
                        "sum_other_doc_count": 999999,
                        "buckets": [
                            {
                                "key": "Ukraine",
                                "doc_count": 11111
                            },
                            {
                                "key": "Russia",
                                "doc_count": 22222
                            },
                            {
                                "key": "Poland",
                                "doc_count": 33333
                            }
                        ]
                    }
                },
                {
                    "key_as_string": "2021-10-15",
                    "key": 1634256000000,
                    "doc_count": 255739,
                    "country-agg": {
                        "doc_count_error_upper_bound": 0,
                        "sum_other_doc_count": 666666,
                        "buckets": [
                            {
                                "key": "Ukraine",
                                "doc_count": 11111
                            },
                            {
                                "key": "Russia",
                                "doc_count": 22222
                            }
                        ]
                    }
                },
                {
                    "key_as_string": "2021-10-16",
                    "key": 1634342400000,
                    "doc_count": 233984,
                    "country-agg": {
                        "doc_count_error_upper_bound": 0,
                        "sum_other_doc_count": 233984,
                        "buckets": []
                    }
                }, 
                // and other
            ]
        }
    }
}



Обработка поиска на php:
logic

$countries = [];

foreach ($chartDataByInterval['agg-date']['buckets'] as $bucket) {
    if (
        $bucket['key'] / 1000 >= strtotime($startInterval)
        && $bucket['key'] / 1000 <= strtotime($endInterval)
    ) {
        if (!empty($bucket['group_by_state']['buckets'])) {
            foreach ($bucket['group_by_state']['buckets'] as $item) {
                if (array_key_exists($item['key'], $countries)) {
                    $countries[$item['key']] += (int) $item['doc_count'];
                } else {
                    $countries[$item['key']] = (int) $item['doc_count'];
                }
            }
        }
    }
}

return $countries;    // ['Ukraine' => 685817, 'Russia' => 874648, ... other]



Важное дополнение! Цель запроса, найти топ страны среди переданных записей с ID в query.terms

Так вот, как видно объемы данных большие и если запросить их за целый год (а такая возможность есть), то обработка в 2 foreach будет очень долгая, здесь хочеться заменить метод "работает не трогай" на "работает быстро"!

В первую очередь хотелось бы сделать проще запрос на поиск в elasticsearch...
Какие есть варианты?
  • Вопрос задан
  • 634 просмотра
Решения вопроса 1
@Triariy
А зачем вы используете агрегацию "date_histogram", когда это можно сделать одной лишь "terms"? У вас уже есть выборка за месяц в "query", и вы зачем-то ещё раз разбиваете по дням, чтобы потом в коде всё собрать вместе.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы