为什么Elasticsearch术语存储桶大小会影响内部反向嵌套聚合的doc_count?

时间:2018-11-30 15:12:11

标签: elasticsearch elasticsearch-aggregation

我一直在尝试从反向嵌套聚合中跟踪丢失的文档数。

我的查询

"aggs": {
    "mainGrouping": {
      "nested": {
        "path": "parent.child"
      },
      "aggs": {
        "uniqueCount": {
          "cardinality": {
            "field": "parent.child.id"
          }
        },
        "groupBy": {
          "terms": {
            "field": "parent.child.id",
            "size": 20,  <- If I change this, my doc count for noOfParents changes
            "order": [
              {
                "noOfParents": "desc"
              }
            ]
          },
          "aggs": {
            "noOfParents": {
              "reverse_nested": {}
            }
          }
        }
      }
    }

所以我在size:20上运行它。当我知道应该有9个匹配项时,我有一个存储桶返回了7的noOfParents。我无意中注意到,如果我将术语聚合的大小更改为50,则noOfParents在此存储桶中正确显示了9。

为什么术语聚合的大小会影响反向聚合的doc_count?这是预期的行为还是错误?我正在使用Elasticsearch 5.6。

1 个答案:

答案 0 :(得分:1)

您正在观察的是terms聚合的最可能的正常行为,因为文档计数是近似的。这既与reverse_nested无关,也与nested聚合无关。

简而言之,由于数据分布在各个分片上,因此Elasticsearch首先在每个分片上局部进行最佳猜测,然后将结果合并到各个分片上。有关更好,更详细的说明,请查看this section of the documentation

要确保确实如此,您可以添加一个top_hits并启用explain的聚合:

      "aggs": {
        "noOfParents": {
          "reverse_nested": {},
          "aggs": {
            "top hits": {
              "top_hits": {
                "size": 10,
                "explain": true
              }
            }
          }
        }
      }

这将为您提供匹配的父文档及其分片ID的列表。像这样:

  "aggregations": {
    "mainGrouping": {
      ...
      "groupBy": {
        ...
        "buckets": [
          {
            "key": "1",
            "doc_count": 5,
            "noOfParents": {
              "doc_count": 5,
              "top hits": {
                "hits": {
                  "total": 5,
                  "max_score": 1,
                  "hits": [
                    {
                      "_shard": "[my-index-2018-12][0]", <-- this is the shard
                      "_node": "7JNqOhTtROqzQR9QBUENcg",
                      "_index": "my-index-2018-12",
                      "_type": "doc",
                      "_id": "AWdpyZ4Y3HZjlM-Ibd7O",
                      "_score": 1,
                      "_source": {
                        "parent": "A",
                        "child": {
                          "id": "1"
                        }
                      },
                      "_explanation": ...
                    },

证明这是问题根源的另一种方法是将查询隔离在一个分片中。为此,只需在搜索请求中添加routing?routing=0

这将使您的terms桶的数量在一个分片内保持稳定。然后将noOfParents与预期的父母数量(同样,在同一分片中)进行比较。

希望有帮助!