【问题标题】:Can't nest terms aggregations more than two deep without further aggs being ignored?不能在不忽略进一步聚合的情况下嵌套两个以上的术语聚合吗?
【发布时间】:2017-10-19 03:22:37
【问题描述】:

我正在使用 C# 的 Nest 库查询 ElasticSearch,以获取具有多个枢轴的图形数据。每个枢轴都是查询上的嵌套术语聚合,并且使用一个或两个枢轴可以正常工作。但是,一旦我到达三个枢轴,SearchRequest 对象将不会生成进一步的聚合。

构建聚合的代码如下所示:

TermsAggregation topTermAgg = null;
TermsAggregation currentAgg = null;
foreach (var pivotName in activePivots)
{
    newTermAgg = new TermsAggregation("pivot")
    {
        Field = pivot.ToString().ToLower()
    };

    if (topTermAgg == null)
    {
        topTermAgg = newTermAgg;
    }
    else
    {
        currentAgg.Aggregations = newTermAgg;
    }
    currentAgg = newTermAgg;
}

SearchRequest 本身非常简单:

var searchRequest = new SearchRequest(Indices.Index("a", "b", "c"))
{
    Size = 0,
    Aggregations = topTermAgg,
    Query = query,
};

不幸的是,当转换为字符串时,3 个或更多枢轴的 SearchRequest 看起来像这样(通过 nestClient.Serializer.SerializeToString(searchRequest)):

{
  "size": 0,
  "query": {
    "bool": <Fairly complex query, that works fine. It's the aggregation that has the problem.>
  },
  "aggs": {
    "pivot": {
      "terms": {
        "field": "pivot1"
      },
      "aggs": {
        "pivot": {
          "terms": {
            "field": "pivot2"
          }
        }
      }
    }
  }
}

当我在调试器中检查 searchRequest 对象时,它肯定有 3 个或更多聚合。这是怎么回事,如何让 3 个或更多嵌套术语聚合正常工作?

我使用的是 Nest 5.01 版。

【问题讨论】:

    标签: elasticsearch nest


    【解决方案1】:

    这必须与您构建嵌套聚合的方式有关。 Arbitrarily deep nested aggregations can be built 与客户。这是一个三层嵌套聚合的示例

    client.Search<Question>(s => s
        .Aggregations(a => a
            .Terms("top", ta => ta
                .Field("top_field")
                .Aggregations(aa => aa
                    .Terms("nested_1", nta => nta
                        .Field("nested_field_1")
                        .Aggregations(aaa => aaa
                            .Terms("nested_2", nnta => nnta
                                .Field("nested_field_3")
                            )
                        )
                    )
                )
            )
        )
    );
    

    序列化为

    {
      "aggs": {
        "top": {
          "terms": {
            "field": "top_field"
          },
          "aggs": {
            "nested_1": {
              "terms": {
                "field": "nested_field_1"
              },
              "aggs": {
                "nested_2": {
                  "terms": {
                    "field": "nested_field_3"
                  }
                }
              }
            }
          }
        }
      }
    }
    

    你也可以直接给AggregationDictionary加值

    var request = new SearchRequest<Question>
    {
        Aggregations = new AggregationDictionary
        {
            { "top", new TermsAggregation("top")
                {
                    Field = "top_field",
                    Aggregations = new AggregationDictionary
                    {
                        { "nested_1", new TermsAggregation("nested_1")
                            {
                                Field = "nested_field_1",
                                Aggregations = new AggregationDictionary
                                {
                                    { "nested_2", new TermsAggregation("nested_2")
                                        {
                                            Field = "nested_field_2"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    };
    
    client.Search<Question>(request);
    

    与上一个请求相同。您可以将其进一步缩短为

    var request = new SearchRequest<Question>
    {
        Aggregations = new TermsAggregation("top")
        {
            Field = "top_field",
            Aggregations = new TermsAggregation("nested_1")
            {
                Field = "nested_field_1",
                Aggregations = new TermsAggregation("nested_2")
                {
                    Field = "nested_field_2"
                }
            }
        }
    };
    
    client.Search<Question>(request);
    

    【讨论】:

    • 是的,我同意我的构造方法在某种程度上存在缺陷,但我不确定如何 - 而且 Nest 在强 -类型语言,并且不允许我向现有的 AggregationDictionary 添加任何内容,甚至不允许直接使用值构造 AggregationDictionary。看起来 agg.Aggregations = aTermsAgg 分配仅适用于大约一个级别,然后它以某种方式将类型进一步向下。
    • 它确实允许构造一个带有值的AggregationDictionary;让我添加一个例子
    【解决方案2】:

    我的代码是通过自下而上而不是自上而下构建聚合来工作的。

    var terminalAggregation = <some aggregation. In my code, there's a lowest aggregation that's different from the rest. For the code I presented, you could just build the lowest pivot.>
    TermsAggregation topTermAgg = null;
    activePivots.Reverse();
    foreach (var pivotName in activePivots)
    {
        newTermAgg = new TermsAggregation("pivot")
        {
            Field = pivot.ToString().ToLower(),
            Aggregations = topTermAgg ?? terminalAggregation
        };
    
        topTermAgg = newTermAgg;
    }
    

    这看起来像是 Nest 库中的错误;有不同的类,如 AggregationBase 和 BucketAggregationBase 和 AggregationDictionary 都可以分配给“Aggregations”属性,但是当您递归执行第二次分配后,似乎存在一些细微的缺陷。

    文档也不是最新的:它声称you can create an AggregationDictionary yourself,但由于 AggregationDictionary 没有公共的 Add() 方法,我真的不能。我也不能使用 C# 的 {}-after-insantiation 语法来填充它的属性——同样,因为 Add() 不是公共的。

    【讨论】:

    • 您应该将客户端更新到最新的 5.x 版本; Add() 方法在 5.2.0 中添加到客户端。 5.x 文档是最新的 5.x 源代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-13
    • 2022-01-19
    • 2015-08-26
    • 1970-01-01
    相关资源
    最近更新 更多