Субагрегация приводит к отсутствию данных - PullRequest
0 голосов
/ 08 января 2019

Краткий вопрос : Почему при выполнении запроса с субагрегацией в некоторых случаях внутренняя агрегация пропускает данные?

Подробный вопрос : У меня есть поисковый запрос с подагрегацией (сегменты в сегментах) следующим образом:

{
    "size": 0,
    "aggs": {
        "outer_docs": {
            "terms": {"size": 20, "field": "field_1_to_aggregate_on"},
            "aggs": {
                "inner_docs": {
                    "terms": {"size": 10000, "field": "field_2_to_aggregate_on"},
                    "aggs": "things to display here"
                }
            }
        }
    }
}

Если я выполню этот запрос, для некоторых external_doc я получу не все внутренние документы, связанные с ним. В приведенном ниже выводе есть три внутренних документа для внешнего документа key_1.

{
    "hits": {
        "total": 9853,
        "max_score": 0.0,
        "hits": []
    },
    "aggregations": {
        "outer_docs": {
            "doc_count_error_upper_bound": -1, "sum_other_doc_count": 9801,
            "buckets": [
                {
                    "key": "key_1", "doc_count": 3,
                    "inner_docs": {
                        "doc_count_error_upper_bound": 0,
                        "sum_other_doc_count": 0,
                        "buckets": [
                            {"key": "1", "doc_count": 1, "some": "data here"},
                            ...
                            {"key": "3", "doc_count": 1, "some": "data here"},
                        ]
                    }
                },
                ...
            ]
        }
    }
}

Теперь я добавляю запрос, чтобы в одиночку выбрать один external_doc, который в любом случае был бы в первых 20.

"query": {"bool": {"must": [{'term': {'field_1_to_aggregate_on': 'key_1'}}]}}

В этом случае я получаю все inner_docs, которые находятся в выходных данных ниже семи внутренних документов для внешнего ключа key_1.

{
    "hits": {
        "total": 8,
        "max_score": 0.0,
        "hits": []
    },
    "aggregations": {
        "outer_docs": {
            "doc_count_error_upper_bound": -1, "sum_other_doc_count": 9801,
            "buckets": [
                {
                    "key": "key_1", "doc_count": 8,
                    "inner_docs": {
                        "doc_count_error_upper_bound": 0,
                        "sum_other_doc_count": 0,
                        "buckets": [
                            {"key": "1", "doc_count": 1, "some": "data here"},
                            ...
                            {"key": "7", "doc_count": 2, "some": "data here"},
                        ]
                    }
                },
                ...
            ]
        }
    }
}

Я явно указал, что мне нужно 10 000 inner_docs на external_doc. Что мешает мне получить все данные?

Это информация о моей версии:

{
    'build_date': '2018-09-26T13:34:09.098244Z',
    'build_flavor': 'default',
    'build_hash': '04711c2',
    'build_snapshot': False,
    'build_type': 'deb',
    'lucene_version': '7.4.0',
    'minimum_index_compatibility_version': '5.0.0',
    'minimum_wire_compatibility_version': '5.6.0',
    'number': '6.4.2'
}

РЕДАКТИРОВАТЬ : Покопавшись еще немного, я обнаружил, что проблема связана не с субагрегацией, а с самой агрегацией и использованием сегментов. Я открыл этот отчет об ошибке для Elastic об этом:

Ответы [ 3 ]

0 голосов
/ 11 января 2019

Проверьте ваш эластичный файл журнала амортизации. Вы, вероятно, будете иметь несколько предупреждений, подобных этому:

This aggregation creates too many buckets (10001) and will throw an error in future versions. You should update the [search.max_buckets] cluster setting or use the [composite] aggregation to paginate all buckets in multiple requests.

search.max_buckets - это параметр динамического кластера, который по умолчанию равен 10 000 сегментов в 7.0.

Теперь, это нигде не задокументировано, но по моему опыту: выделение более 10.000 сегментов приведет к завершению вашего запроса, но вы вернете результаты, которые были достигнуты до этого момента. Это объясняет отсутствие данных в вашем результате

Использование составного агрегирования поможет, другой вариант - увеличить max_buckets. Будьте осторожны с этим, вы можете таким образом вывести из строя весь ваш кластер, потому что за каждый сегмент (ОЗУ) приходится платить. Неважно, используете ли вы все выделенные сегменты, вы можете потерпеть крах только с пустыми сегментами.

См .:

https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking-changes-7.0.html#_literal_search_max_buckets_literal_in_the_cluster_setting https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket.html https://github.com/elastic/elasticsearch/issues/35896

0 голосов
/ 15 января 2019

Оказалось, что проблема не в субагрегации, а в том, что это актуальная функция ElasticSearch. Мы используем 5 осколков, а при использовании осколков агрегаты дают только приблизительные результаты.

Мы сделали эту проблему воспроизводимой и разместили ее на Упругом дискуссионном форуме . Там мы узнали, что агрегаты не всегда возвращают все данные со ссылкой на документацию , где это объясняется более подробно.

Мы также узнали, что использование только 1 осколка решает проблему, а когда это невозможно, параметр shard_size может облегчить проблему.

0 голосов
/ 11 января 2019

Как насчет использования агрегации composite для этого? Уверен, что это решит вашу проблему.

GET /_search
{
    "aggs" : {
        "all_docs": {
            "composite" : {
                "size": 1000,
                "sources" : [
                    { "outer_docs": { "terms": { "field": "field_1_to_aggregate_on" } } },
                    { "inner_docs": { "terms": { "field": "field_2_to_aggregate_on" } } }
                ]
            }
        }
    }
}

Если у вас много сегментов, составная агрегация поможет вам прокрутить каждый из них, используя size / after.

...