Skip to content

[Backport 8.1] Support sub-aggs for single bucket aggregations #6635

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,3 @@
namespace Elastic.Clients.Elasticsearch.Aggregations;

public interface IAggregate { }

/// <summary>
/// Base class for all aggregates.
/// </summary>
public abstract class Aggregate : IAggregate
{
}


Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public sealed class GetSnapshotRequestParameters : RequestParameters<GetSnapshot
[JsonIgnore]
public bool? IndexDetails { get => Q<bool?>("index_details"); set => Q("index_details", value); }

[JsonIgnore]
public bool? IndexNames { get => Q<bool?>("index_names"); set => Q("index_names", value); }

[JsonIgnore]
public bool? IncludeRepository { get => Q<bool?>("include_repository"); set => Q("include_repository", value); }

Expand Down Expand Up @@ -85,6 +88,9 @@ public GetSnapshotRequest(Elastic.Clients.Elasticsearch.Name repository, Elastic
[JsonIgnore]
public bool? IndexDetails { get => Q<bool?>("index_details"); set => Q("index_details", value); }

[JsonIgnore]
public bool? IndexNames { get => Q<bool?>("index_names"); set => Q("index_names", value); }

[JsonIgnore]
public bool? IncludeRepository { get => Q<bool?>("include_repository"); set => Q("include_repository", value); }

Expand Down Expand Up @@ -129,6 +135,7 @@ internal GetSnapshotRequestDescriptor()
public GetSnapshotRequestDescriptor IgnoreUnavailable(bool? ignoreUnavailable = true) => Qs("ignore_unavailable", ignoreUnavailable);
public GetSnapshotRequestDescriptor IncludeRepository(bool? includeRepository = true) => Qs("include_repository", includeRepository);
public GetSnapshotRequestDescriptor IndexDetails(bool? indexDetails = true) => Qs("index_details", indexDetails);
public GetSnapshotRequestDescriptor IndexNames(bool? indexNames = true) => Qs("index_names", indexNames);
public GetSnapshotRequestDescriptor MasterTimeout(Elastic.Clients.Elasticsearch.Duration? masterTimeout) => Qs("master_timeout", masterTimeout);
public GetSnapshotRequestDescriptor Offset(int? offset) => Qs("offset", offset);
public GetSnapshotRequestDescriptor Order(Elastic.Clients.Elasticsearch.SortOrder? order) => Qs("order", order);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class AdjacencyMatrixAggregate : Aggregate
public sealed partial class AdjacencyMatrixAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("buckets")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class AutoDateHistogramAggregate : Aggregate
public sealed partial class AutoDateHistogramAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("buckets")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class AvgAggregate : Aggregate
public sealed partial class AvgAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("meta")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class BoxPlotAggregate : Aggregate
public sealed partial class BoxPlotAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("lower")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class CardinalityAggregate : Aggregate
public sealed partial class CardinalityAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("meta")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class ChildrenAggregate : Aggregate
[JsonConverter(typeof(ChildrenAggregateConverter))]
public sealed partial class ChildrenAggregate : AggregateDictionary, IAggregate
{
[JsonInclude]
[JsonPropertyName("aggregations")]
public Elastic.Clients.Elasticsearch.Aggregations.AggregateDictionary Aggregations { get; init; }
public ChildrenAggregate(IReadOnlyDictionary<string, IAggregate> backingDictionary) : base(backingDictionary)
{
}

[JsonInclude]
[JsonPropertyName("doc_count")]
Expand All @@ -38,4 +39,49 @@ public sealed partial class ChildrenAggregate : Aggregate
[JsonPropertyName("meta")]
public Dictionary<string, object>? Meta { get; init; }
}

internal sealed class ChildrenAggregateConverter : JsonConverter<ChildrenAggregate>
{
public override ChildrenAggregate? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException($"Expected {JsonTokenType.StartObject} but read {reader.TokenType}.");
var subAggs = new Dictionary<string, IAggregate>(); // TODO - Optimise this and only create if we need it.
long docCount = default;
Dictionary<string, object>? meta = default;
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
break;
if (reader.TokenType != JsonTokenType.PropertyName)
throw new JsonException($"Expected {JsonTokenType.PropertyName} but read {reader.TokenType}.");
var name = reader.GetString(); // TODO: Future optimisation, get raw bytes span and parse based on those
reader.Read();
if (name.Equals("doc_count", StringComparison.Ordinal))
{
docCount = JsonSerializer.Deserialize<long>(ref reader, options);
continue;
}

if (name.Equals("meta", StringComparison.Ordinal))
{
meta = JsonSerializer.Deserialize<Dictionary<string, object>?>(ref reader, options);
continue;
}

if (name.Contains("#"))
{
AggregateDictionaryConverter.ReadAggregate(ref reader, options, subAggs, name);
continue;
}

throw new JsonException("Unknown property read from JSON.");
}

return new ChildrenAggregate(subAggs)
{ DocCount = docCount, Meta = meta };
}

public override void Write(Utf8JsonWriter writer, ChildrenAggregate value, JsonSerializerOptions options) => throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class CompositeAggregate : Aggregate
public sealed partial class CompositeAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("after_key")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class CumulativeCardinalityAggregate : Aggregate
public sealed partial class CumulativeCardinalityAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("meta")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class DateHistogramAggregate : Aggregate
public sealed partial class DateHistogramAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("buckets")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class DateRangeAggregate : Aggregate
public sealed partial class DateRangeAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("buckets")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class DerivativeAggregate : Aggregate
public sealed partial class DerivativeAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("meta")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class DoubleTermsAggregate : Aggregate
public sealed partial class DoubleTermsAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("buckets")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class ExtendedStatsAggregate : Aggregate
public sealed partial class ExtendedStatsAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("avg")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class ExtendedStatsBucketAggregate : Aggregate
public sealed partial class ExtendedStatsBucketAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("avg")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class FilterAggregate : Aggregate
[JsonConverter(typeof(FilterAggregateConverter))]
public sealed partial class FilterAggregate : AggregateDictionary, IAggregate
{
[JsonInclude]
[JsonPropertyName("aggregations")]
public Elastic.Clients.Elasticsearch.Aggregations.AggregateDictionary Aggregations { get; init; }
public FilterAggregate(IReadOnlyDictionary<string, IAggregate> backingDictionary) : base(backingDictionary)
{
}

[JsonInclude]
[JsonPropertyName("doc_count")]
Expand All @@ -38,4 +39,49 @@ public sealed partial class FilterAggregate : Aggregate
[JsonPropertyName("meta")]
public Dictionary<string, object>? Meta { get; init; }
}

internal sealed class FilterAggregateConverter : JsonConverter<FilterAggregate>
{
public override FilterAggregate? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException($"Expected {JsonTokenType.StartObject} but read {reader.TokenType}.");
var subAggs = new Dictionary<string, IAggregate>(); // TODO - Optimise this and only create if we need it.
long docCount = default;
Dictionary<string, object>? meta = default;
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
break;
if (reader.TokenType != JsonTokenType.PropertyName)
throw new JsonException($"Expected {JsonTokenType.PropertyName} but read {reader.TokenType}.");
var name = reader.GetString(); // TODO: Future optimisation, get raw bytes span and parse based on those
reader.Read();
if (name.Equals("doc_count", StringComparison.Ordinal))
{
docCount = JsonSerializer.Deserialize<long>(ref reader, options);
continue;
}

if (name.Equals("meta", StringComparison.Ordinal))
{
meta = JsonSerializer.Deserialize<Dictionary<string, object>?>(ref reader, options);
continue;
}

if (name.Contains("#"))
{
AggregateDictionaryConverter.ReadAggregate(ref reader, options, subAggs, name);
continue;
}

throw new JsonException("Unknown property read from JSON.");
}

return new FilterAggregate(subAggs)
{ DocCount = docCount, Meta = meta };
}

public override void Write(Utf8JsonWriter writer, FilterAggregate value, JsonSerializerOptions options) => throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class FiltersAggregate : Aggregate
public sealed partial class FiltersAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("buckets")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class GlobalAggregate : Aggregate
[JsonConverter(typeof(GlobalAggregateConverter))]
public sealed partial class GlobalAggregate : AggregateDictionary, IAggregate
{
[JsonInclude]
[JsonPropertyName("aggregations")]
public Elastic.Clients.Elasticsearch.Aggregations.AggregateDictionary Aggregations { get; init; }
public GlobalAggregate(IReadOnlyDictionary<string, IAggregate> backingDictionary) : base(backingDictionary)
{
}

[JsonInclude]
[JsonPropertyName("doc_count")]
Expand All @@ -38,4 +39,49 @@ public sealed partial class GlobalAggregate : Aggregate
[JsonPropertyName("meta")]
public Dictionary<string, object>? Meta { get; init; }
}

internal sealed class GlobalAggregateConverter : JsonConverter<GlobalAggregate>
{
public override GlobalAggregate? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
throw new JsonException($"Expected {JsonTokenType.StartObject} but read {reader.TokenType}.");
var subAggs = new Dictionary<string, IAggregate>(); // TODO - Optimise this and only create if we need it.
long docCount = default;
Dictionary<string, object>? meta = default;
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
break;
if (reader.TokenType != JsonTokenType.PropertyName)
throw new JsonException($"Expected {JsonTokenType.PropertyName} but read {reader.TokenType}.");
var name = reader.GetString(); // TODO: Future optimisation, get raw bytes span and parse based on those
reader.Read();
if (name.Equals("doc_count", StringComparison.Ordinal))
{
docCount = JsonSerializer.Deserialize<long>(ref reader, options);
continue;
}

if (name.Equals("meta", StringComparison.Ordinal))
{
meta = JsonSerializer.Deserialize<Dictionary<string, object>?>(ref reader, options);
continue;
}

if (name.Contains("#"))
{
AggregateDictionaryConverter.ReadAggregate(ref reader, options, subAggs, name);
continue;
}

throw new JsonException("Unknown property read from JSON.");
}

return new GlobalAggregate(subAggs)
{ DocCount = docCount, Meta = meta };
}

public override void Write(Utf8JsonWriter writer, GlobalAggregate value, JsonSerializerOptions options) => throw new NotImplementedException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class HistogramAggregate : Aggregate
public sealed partial class HistogramAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("buckets")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class InferenceAggregate : Aggregate
public sealed partial class InferenceAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("data")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#nullable restore
namespace Elastic.Clients.Elasticsearch.Aggregations
{
public sealed partial class IpRangeAggregate : Aggregate
public sealed partial class IpRangeAggregate : IAggregate
{
[JsonInclude]
[JsonPropertyName("buckets")]
Expand Down
Loading