简短的问题:在执行带有子聚合的查询时,内部聚合为什么在某些情况下会丢失数据?
详细问题:我有一个带有子聚合(存储桶中的存储桶)的搜索查询,如下所示:
{
"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_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"},
]
}
},
...
]
}
}
}
现在,我添加一个查询以单选一个反而会在前20个中使用的external_doc。
"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'
}
编辑:经过更多的研究,我发现问题与子聚合无关,但与聚合本身和分片的使用无关。我已经为Elastic打开了此错误报告:
答案 0 :(得分:1)
为此使用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
滚动浏览每个存储桶。
答案 1 :(得分:1)
检查弹性弃用日志文件。您可能会收到如下警告:
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中默认为10.000个存储桶。
现在,这在任何地方都没有记录,但是根据我的经验:分配超过10.000个存储桶会导致查询终止,但是您会取回在那一刻之前已经获得的结果。这说明了结果中缺少数据
使用复合聚合将有所帮助,您的另一个选择是增加max_buckets。请注意,这样可能会使整个群集崩溃,因为每个存储区(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
答案 2 :(得分:0)
事实证明,问题并非归因于子聚合,而这是ElasticSearch的实际功能。我们使用5个分片,而使用分片时,聚合仅返回近似结果。
我们已使此问题可重现,并将其发布在Elastic discuss forum中。在那里,我们了解到聚合并不总是返回所有数据,而是指向documentation的链接,其中对此进行了更详细的说明。
我们还了解到,仅使用1个分片即可解决该问题,并且在不可能的情况下,参数shard_size
可以缓解此问题。