Skip to content

Commit a6bf6b2

Browse files
Fixes and tests relating to aggregations (#6741) (#6743)
Co-authored-by: Steve Gordon <sgordon@hotmail.co.uk>
1 parent dd314ff commit a6bf6b2

File tree

11 files changed

+173
-60
lines changed

11 files changed

+173
-60
lines changed

src/Elastic.Clients.Elasticsearch/Common/Aggregations/Aggregation.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
namespace Elastic.Clients.Elasticsearch.Aggregations;
66

7-
public interface IAggregation
7+
// This is marked as internal for now, until we are ready to support plugin aggregations.
8+
internal interface IAggregation
89
{
910
string? Name { get; }
1011
}

src/Elastic.Clients.Elasticsearch/Serialization/AggregationContainerSerializationHelper.cs

+3-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
namespace Elastic.Clients.Elasticsearch
99
{
10-
1110
internal static class AggregationContainerSerializationHelper
1211
{
1312
public static AggregationContainer ReadContainer<T>(ref Utf8JsonReader reader, JsonSerializerOptions options) where T : Aggregation
@@ -21,13 +20,12 @@ public static AggregationContainer ReadContainer<T>(ref Utf8JsonReader reader, J
2120

2221
public static AggregationContainer ReadContainer<T>(string variantName, ref Utf8JsonReader reader, JsonSerializerOptions options) where T : Aggregation
2322
{
24-
var variant = JsonSerializer.Deserialize<T?>(ref reader, options);
25-
26-
//variant.Name = variantName;
23+
var variant = JsonSerializer.Deserialize<T>(ref reader, options);
2724

2825
var container = new AggregationContainer(variant);
2926

30-
//reader.Read();
27+
if (container.Variant is Aggregation agg)
28+
agg.Name = variantName;
3129

3230
return container;
3331
}

src/Elastic.Clients.Elasticsearch/Serialization/IsADictionaryConverter.cs

-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ public override void Write(Utf8JsonWriter writer, TType value, JsonSerializerOpt
5353
}
5454
}
5555

56-
5756
internal interface IUnionVerifiable
5857
{
5958
bool IsSuccessful { get; }

src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregationContainer.cs

+2-29
Original file line numberDiff line numberDiff line change
@@ -30,34 +30,7 @@ public partial class AggregationContainer
3030
JsonSerializer.Serialize(writer, descriptor, options);
3131
};
3232

33-
public static implicit operator AggregationContainer(Aggregation aggregator)
34-
{
35-
if (aggregator == null)
36-
return null;
37-
38-
// TODO: Reimplement this fully - as neccesary!
39-
40-
var container = new AggregationContainer(aggregator)
41-
{
42-
//Meta = aggregator.Meta
43-
};
44-
45-
//aggregator.WrapInContainer(container);
46-
47-
//var bucket = aggregator as BucketAggregationBase;
48-
49-
//container.Aggregations = bucket?.Aggregations;
50-
51-
var combinator = aggregator as AggregationCombinator;
52-
if (combinator?.Aggregations != null)
53-
{
54-
var dict = new AggregationDictionary();
55-
// foreach (var agg in combinator.Aggregations)
56-
// dict.Add(((IAggregation)agg).Name, agg);
57-
// container.Aggregations = dict;
58-
}
59-
60-
return container;
61-
}
33+
public static implicit operator AggregationContainer(Aggregation aggregator) =>
34+
aggregator == null ? null : new AggregationContainer(aggregator);
6235
}
6336
}

src/Elastic.Clients.Elasticsearch/_Generated/Types/Aggregations/AggregationContainer.g.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace Elastic.Clients.Elasticsearch.Aggregations
2727
[JsonConverter(typeof(AggregationContainerConverter))]
2828
public sealed partial class AggregationContainer
2929
{
30-
public AggregationContainer(IAggregation variant) => Variant = variant ?? throw new ArgumentNullException(nameof(variant));
30+
internal AggregationContainer(IAggregation variant) => Variant = variant ?? throw new ArgumentNullException(nameof(variant));
3131
internal IAggregation Variant { get; }
3232
}
3333

src/Elastic.Clients.Elasticsearch/_Generated/Types/IndexManagement/MappingLimitSettings.g.cs

+18
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ namespace Elastic.Clients.Elasticsearch.IndexManagement
2626
{
2727
public sealed partial class MappingLimitSettings
2828
{
29+
[JsonInclude]
30+
[JsonPropertyName("coerce")]
31+
public bool? Coerce { get; set; }
32+
2933
[JsonInclude]
3034
[JsonPropertyName("depth")]
3135
public Elastic.Clients.Elasticsearch.IndexManagement.MappingLimitSettingsDepth? Depth { get; set; }
@@ -62,6 +66,8 @@ public MappingLimitSettingsDescriptor() : base()
6266
{
6367
}
6468

69+
private bool? CoerceValue { get; set; }
70+
6571
private Elastic.Clients.Elasticsearch.IndexManagement.MappingLimitSettingsDepth? DepthValue { get; set; }
6672

6773
private MappingLimitSettingsDepthDescriptor DepthDescriptor { get; set; }
@@ -100,6 +106,12 @@ public MappingLimitSettingsDescriptor() : base()
100106

101107
private Action<MappingLimitSettingsTotalFieldsDescriptor> TotalFieldsDescriptorAction { get; set; }
102108

109+
public MappingLimitSettingsDescriptor Coerce(bool? coerce = true)
110+
{
111+
CoerceValue = coerce;
112+
return Self;
113+
}
114+
103115
public MappingLimitSettingsDescriptor Depth(Elastic.Clients.Elasticsearch.IndexManagement.MappingLimitSettingsDepth? depth)
104116
{
105117
DepthDescriptor = null;
@@ -253,6 +265,12 @@ public MappingLimitSettingsDescriptor TotalFields(Action<MappingLimitSettingsTot
253265
protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings)
254266
{
255267
writer.WriteStartObject();
268+
if (CoerceValue.HasValue)
269+
{
270+
writer.WritePropertyName("coerce");
271+
writer.WriteBooleanValue(CoerceValue.Value);
272+
}
273+
256274
if (DepthDescriptor is not null)
257275
{
258276
writer.WritePropertyName("depth");

src/Elastic.Clients.Elasticsearch/_Generated/Types/IndexManagement/RolloverConditions.g.cs

+41-23
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,9 @@ public sealed partial class RolloverConditions
4646
[JsonPropertyName("max_primary_shard_size")]
4747
public Elastic.Clients.Elasticsearch.ByteSize? MaxPrimaryShardSize { get; set; }
4848

49-
[JsonInclude]
50-
[JsonPropertyName("max_primary_shard_size_bytes")]
51-
public Elastic.Clients.Elasticsearch.ByteSize? MaxPrimaryShardSizeBytes { get; set; }
52-
5349
[JsonInclude]
5450
[JsonPropertyName("max_size")]
55-
public string? MaxSize { get; set; }
51+
public Elastic.Clients.Elasticsearch.ByteSize? MaxSize { get; set; }
5652

5753
[JsonInclude]
5854
[JsonPropertyName("max_size_bytes")]
@@ -69,6 +65,14 @@ public sealed partial class RolloverConditions
6965
[JsonInclude]
7066
[JsonPropertyName("min_primary_shard_docs")]
7167
public long? MinPrimaryShardDocs { get; set; }
68+
69+
[JsonInclude]
70+
[JsonPropertyName("min_primary_shard_size")]
71+
public Elastic.Clients.Elasticsearch.ByteSize? MinPrimaryShardSize { get; set; }
72+
73+
[JsonInclude]
74+
[JsonPropertyName("min_size")]
75+
public Elastic.Clients.Elasticsearch.ByteSize? MinSize { get; set; }
7276
}
7377

7478
public sealed partial class RolloverConditionsDescriptor : SerializableDescriptorBase<RolloverConditionsDescriptor>
@@ -88,9 +92,7 @@ public RolloverConditionsDescriptor() : base()
8892

8993
private Elastic.Clients.Elasticsearch.ByteSize? MaxPrimaryShardSizeValue { get; set; }
9094

91-
private Elastic.Clients.Elasticsearch.ByteSize? MaxPrimaryShardSizeBytesValue { get; set; }
92-
93-
private string? MaxSizeValue { get; set; }
95+
private Elastic.Clients.Elasticsearch.ByteSize? MaxSizeValue { get; set; }
9496

9597
private Elastic.Clients.Elasticsearch.ByteSize? MaxSizeBytesValue { get; set; }
9698

@@ -100,6 +102,10 @@ public RolloverConditionsDescriptor() : base()
100102

101103
private long? MinPrimaryShardDocsValue { get; set; }
102104

105+
private Elastic.Clients.Elasticsearch.ByteSize? MinPrimaryShardSizeValue { get; set; }
106+
107+
private Elastic.Clients.Elasticsearch.ByteSize? MinSizeValue { get; set; }
108+
103109
public RolloverConditionsDescriptor MaxAge(Elastic.Clients.Elasticsearch.Duration? maxAge)
104110
{
105111
MaxAgeValue = maxAge;
@@ -130,13 +136,7 @@ public RolloverConditionsDescriptor MaxPrimaryShardSize(Elastic.Clients.Elastics
130136
return Self;
131137
}
132138

133-
public RolloverConditionsDescriptor MaxPrimaryShardSizeBytes(Elastic.Clients.Elasticsearch.ByteSize? maxPrimaryShardSizeBytes)
134-
{
135-
MaxPrimaryShardSizeBytesValue = maxPrimaryShardSizeBytes;
136-
return Self;
137-
}
138-
139-
public RolloverConditionsDescriptor MaxSize(string? maxSize)
139+
public RolloverConditionsDescriptor MaxSize(Elastic.Clients.Elasticsearch.ByteSize? maxSize)
140140
{
141141
MaxSizeValue = maxSize;
142142
return Self;
@@ -166,6 +166,18 @@ public RolloverConditionsDescriptor MinPrimaryShardDocs(long? minPrimaryShardDoc
166166
return Self;
167167
}
168168

169+
public RolloverConditionsDescriptor MinPrimaryShardSize(Elastic.Clients.Elasticsearch.ByteSize? minPrimaryShardSize)
170+
{
171+
MinPrimaryShardSizeValue = minPrimaryShardSize;
172+
return Self;
173+
}
174+
175+
public RolloverConditionsDescriptor MinSize(Elastic.Clients.Elasticsearch.ByteSize? minSize)
176+
{
177+
MinSizeValue = minSize;
178+
return Self;
179+
}
180+
169181
protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings)
170182
{
171183
writer.WriteStartObject();
@@ -199,16 +211,10 @@ protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions o
199211
JsonSerializer.Serialize(writer, MaxPrimaryShardSizeValue, options);
200212
}
201213

202-
if (MaxPrimaryShardSizeBytesValue is not null)
203-
{
204-
writer.WritePropertyName("max_primary_shard_size_bytes");
205-
JsonSerializer.Serialize(writer, MaxPrimaryShardSizeBytesValue, options);
206-
}
207-
208-
if (!string.IsNullOrEmpty(MaxSizeValue))
214+
if (MaxSizeValue is not null)
209215
{
210216
writer.WritePropertyName("max_size");
211-
writer.WriteStringValue(MaxSizeValue);
217+
JsonSerializer.Serialize(writer, MaxSizeValue, options);
212218
}
213219

214220
if (MaxSizeBytesValue is not null)
@@ -235,6 +241,18 @@ protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions o
235241
writer.WriteNumberValue(MinPrimaryShardDocsValue.Value);
236242
}
237243

244+
if (MinPrimaryShardSizeValue is not null)
245+
{
246+
writer.WritePropertyName("min_primary_shard_size");
247+
JsonSerializer.Serialize(writer, MinPrimaryShardSizeValue, options);
248+
}
249+
250+
if (MinSizeValue is not null)
251+
{
252+
writer.WritePropertyName("min_size");
253+
JsonSerializer.Serialize(writer, MinSizeValue, options);
254+
}
255+
238256
writer.WriteEndObject();
239257
}
240258
}

src/Playground/Program.cs

+3
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
// See the LICENSE file in the project root for more information.
44

55
using Elastic.Clients.Elasticsearch;
6+
using Elastic.Clients.Elasticsearch.Aggregations;
67
using Elastic.Clients.Elasticsearch.IndexManagement;
78
using Elastic.Transport;
89
using Playground;
910

1011
// const string IndexName = "stock-demo-v1";
1112

13+
AggregationContainer a = new TermsAggregation("test");
14+
1215
var settings = new ElasticsearchClientSettings(new InMemoryConnection())
1316
.DefaultIndex("default-index")
1417
.DefaultMappingFor<Person>(m => m

tests/Tests/Serialization/Aggregations/ChildrenAggregateSerializationTests.cs

+2
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44

55
using System.Linq;
66
using Elastic.Clients.Elasticsearch.Experimental;
7+
using VerifyXunit;
78

89
namespace Tests.Serialization;
910

11+
[UsesVerify]
1012
public class ChildrenAggregateSerializationTests : SerializerTestBase
1113
{
1214
[U]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Threading.Tasks;
6+
using Elastic.Clients.Elasticsearch.Aggregations;
7+
using Tests.Domain;
8+
using VerifyXunit;
9+
10+
namespace Tests.Serialization;
11+
12+
[UsesVerify]
13+
public class WritingAggregationsTests : SerializerTestBase
14+
{
15+
[U]
16+
public async Task CanSerializeAggregationsWrittenInVariousWays_WhichIncludeMultipleSubAggregations()
17+
{
18+
// TODO - Test other cases from https://www.elastic.co/guide/en/elasticsearch/client/net-api/7.17/writing-aggregations.html#writing-aggregations
19+
20+
// ** First test that the descriptor produces the expected JSON.
21+
22+
var descriptor = new AggregationContainerDescriptor(aggs => aggs
23+
.Children<CommitActivity>("name_of_child_agg", child => child
24+
.Type("commits")
25+
.Aggregations(childAggs => childAggs
26+
.Avg("average_per_child", avg => avg.Field(p => p.ConfidenceFactor))
27+
.Max("max_per_child", max => max.Field(p => p.ConfidenceFactor))
28+
.Min("min_per_child", min => min.Field(p => p.ConfidenceFactor))
29+
)));
30+
31+
var json = await SerializeAndGetJsonStringAsync(descriptor);
32+
33+
await Verifier.VerifyJson(json);
34+
35+
// ** Then test that the object initializer dictionary approach produces the expected (and same) JSON.
36+
37+
var aggs = new AggregationDictionary
38+
{
39+
{
40+
"name_of_child_agg", new ChildrenAggregation("name_of_child_agg")
41+
{
42+
Type = "commits",
43+
Aggregations = new AggregationDictionary
44+
{
45+
{"average_per_child", new AverageAggregation("average_per_child", "confidenceFactor")},
46+
{"max_per_child", new MaxAggregation("max_per_child", "confidenceFactor")},
47+
{"min_per_child", new MinAggregation("min_per_child", "confidenceFactor")},
48+
}
49+
}
50+
}
51+
};
52+
53+
var objectInitializerJson = await SerializeAndGetJsonStringAsync(aggs);
54+
55+
json.Should().Be(objectInitializerJson);
56+
57+
// ** Next test the terser object initializer syntax produces the expected (and same) JSON.
58+
59+
AggregationDictionary terseAggs = new ChildrenAggregation("name_of_child_agg") // NOTE: Must assign to AggregationDictionary.
60+
{
61+
Type = "commits",
62+
Aggregations =
63+
new AverageAggregation("average_per_child", Infer.Field<CommitActivity>(p => p.ConfidenceFactor))
64+
&& new MaxAggregation("max_per_child", Infer.Field<CommitActivity>(p => p.ConfidenceFactor))
65+
&& new MinAggregation("min_per_child", Infer.Field<CommitActivity>(p => p.ConfidenceFactor))
66+
};
67+
68+
var terseAggsJson = await SerializeAndGetJsonStringAsync(terseAggs);
69+
70+
json.Should().Be(terseAggsJson);
71+
72+
// ** Test we can deserialise the JSON as an AggregationDictionary
73+
74+
// TODO
75+
// var result = DeserializeJsonString<AggregationDictionary>(json);
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
name_of_child_agg: {
3+
aggregations: {
4+
average_per_child: {
5+
avg: {
6+
field: confidenceFactor
7+
}
8+
},
9+
max_per_child: {
10+
max: {
11+
field: confidenceFactor
12+
}
13+
},
14+
min_per_child: {
15+
min: {
16+
field: confidenceFactor
17+
}
18+
}
19+
},
20+
children: {
21+
type: commits
22+
}
23+
}
24+
}

0 commit comments

Comments
 (0)