代码之家  ›  专栏  ›  技术社区  ›  physicalattraction

子聚合导致数据丢失

  •  1
  • physicalattraction  · 技术社区  · 6 年前

    简言之 :当使用子聚合执行查询时,为什么在某些情况下内部聚合会丢失数据?

    详细的问题 :我有一个搜索查询,其子聚合(buckets in buckets)如下:

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

    如果我执行这个查询,对于一些外部的文档,我不会收到与它相关联的所有内部的文档。在下面的输出中,有三个内部文档用于外部文档键“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"},
                            ]
                        }
                    },
                    ...
                ]
            }
        }
    }
    

    现在,我添加了一个查询来单独选择一个外部文档,不管怎样,这个外部文档都会出现在前20个文档中。

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

    在这种情况下,我会得到所有的内部文档,它们都在下面七个外部文档键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"},
                            ]
                        }
                    },
                    ...
                ]
            }
        }
    }
    

    我已明确指定,我希望每个外部文档有10000个内部文档。什么阻止了我获取所有数据?

    这是我的版本信息:

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

    编辑 :再多挖掘一点,我发现这个问题与子聚集无关,而是与聚集本身和碎片的使用无关。我已打开此Bug报告以获取弹性:

    3 回复  |  直到 6 年前
        1
  •  1
  •   Val    6 年前

    用这个怎么样 composite aggregation 为了这个?这肯定能解决你的问题。

    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 .

        2
  •  1
  •   Atlan da Gonazol    6 年前

    检查你的弹性折旧日志文件。您可能会收到如下警告:

    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是一个动态集群设置,默认为7.0中的10000个buckets。

    现在,这在任何地方都没有记录,但在我的经验中:分配超过10000个存储桶会导致查询终止,但是在那一刻之前,您将得到已经获得的结果。这就解释了结果中缺少的数据

    使用复合聚合将有助于提高最大存储桶数。小心点,这样可以使整个集群崩溃,因为每个桶(RAM)都有成本。不管您是否实际使用了所有分配的存储桶,您只能使用空的存储桶崩溃。

    见:

    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

        3
  •  0
  •   physicalattraction    6 年前

    结果表明,问题不是由于子聚集,而是弹性搜索的一个实际特征。我们使用5个碎片,当使用碎片时,聚合只返回近似结果。

    我们已将此问题复制,并将其发布到 Elastic discuss forum . 在那里,我们了解到聚合并不总是返回所有的数据,它有一个指向 documentation 这里更详细地解释了这一点。

    我们还了解到,仅使用1个碎片就可以解决问题,当这不可能时,参数 shard_size 可以缓解问题。