Субагрегация приводит к отсутствию данных

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

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

{
    "size": 0,
    "aggs": {
        "outer_docs": {
            "terms": {"size": 20, "field": "field_1_to_aggregate_on"},
            "aggs": {
                "inner_docs": {
                    "terms": {"size": 10000, "field": "field
{
    "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"},
                        ]
                    }
                },
                ...
            ]
        }
    }
}
to_aggregate_on"}, "aggs": "things to display here" } } } } }

Если я выполняю этот запрос, для некоторых external_docs я получаю не все inner_docs, которые с ним связаны. В приведенном ниже выводе есть три внутренних документа для внешнего документа 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 внутренних_документов на каждый внешний_документ. Что мешает мне получить все данные?

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

{
    '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'
}

EDIT: немного покопавшись, я обнаружил, что проблема связана не с субагрегацией, а с самой агрегацией и использованием осколков. Я открыл этот отчет об ошибке для Elastic об этом:


person physicalattraction    schedule 08.01.2019    source источник
comment
"sum_other_doc_count": 9801 здесь указание. Могу я спросить, сколько inner_docs ведер появляется для каждого из outer_docs?   -  person Val    schedule 11.01.2019
comment
Что это означает? Честно говоря, я не считаю это большим числом. На каждый external_doc должно быть от 5 до 10 доступных inner_doc. Проблема в том, что мы не видим все эти 5-10.   -  person physicalattraction    schedule 11.01.2019
comment
Эти результаты действительно странные. Я не могу воспроизвести это на 6.3.2 с немного большим объемом данных. Каковы типы полей для field_1_to_aggregate_on и field_2_to_aggregate_on?   -  person Brian Olsen    schedule 12.01.2019
comment
Что произойдет, если вы запустите curl -XPUT localhost:9200/_cluster/settings -d '{"persistent": {"search.max_buckets": 30000}}' ?   -  person Val    schedule 14.01.2019
comment
@BrianOlsen: обе строки.   -  person physicalattraction    schedule 14.01.2019
comment
@Val: настройки максимального количества сегментов изменены, но мы по-прежнему получаем те же результаты. Обратите внимание, что это не проблема достижения предела для сегментов. У нас есть 20 внешних ведер, в каждом из которых менее 10 внутренних ведер. Мы также не превышаем лимит документов, у нас даже нет 10 000 документов.   -  person physicalattraction    schedule 14.01.2019
comment
Да, но эти 20 внешних корзин, кажется, не учитывают все документы. Что вы увидите, если увеличите количество внешних сегментов, скажем, до 50? Вы видите sum_other_doc_count уменьшение?   -  person Val    schedule 15.01.2019
comment
Действительно, при увеличении количества внешних сегментов результаты первых 20 сегментов были более точными. Теперь мы узнали, что эта неточность является особенностью ElasticSearch, о которой я немного подробнее рассказал в ответе ниже.   -  person physicalattraction    schedule 15.01.2019


Ответы (3)


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

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

person Atlan da Gonazol    schedule 11.01.2019
comment
Спасибо за это понимание. Обратите внимание, что моя проблема не в том, что у меня слишком много ведер. У меня есть 20 внешних ведер, каждое из которых содержит менее 10 внутренних ведер. - person physicalattraction; 14.01.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.

person Val    schedule 11.01.2019
comment
Спасибо за ваше предложение. Я вижу две причины, почему это решение не идеально. Во-первых, мне нужно обработать данные в программе, вызывающей ElasticSearch, чтобы построить иерархию. Вторая, более важная причина заключается в том, что мне нужно, чтобы внешние сегменты были упорядочены путем агрегирования всего этого сегмента, а не составного значения external_doc и inner_doc. Порядок важен, так как я возвращаю только 20 лучших ведер. - person physicalattraction; 11.01.2019

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

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

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

person physicalattraction    schedule 15.01.2019