Skip to content

Commit 1e45ee8

Browse files
russcambenbenwilde
andauthored
Fix Extended stats deserialization (#4109)
Supersedes: #4103 Fixes an issue where datetime extended_stats aggregation was getting deserialized as a regular stats aggregation Note that this fix might not impact anything in practice, since when this code is hit, the rest of the fields are "as_string" fields anyways (in the response examples I'm aware of). Add a unit test to assert that the change to AggregateJsonConverter for ExtendedStats aggregation can deserialize the provided response. Co-authored-by: benbenwilde <[email protected]>
1 parent a8e8108 commit 1e45ee8

File tree

2 files changed

+111
-17
lines changed

2 files changed

+111
-17
lines changed

src/Nest/Aggregations/AggregateJsonConverter.cs

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -311,18 +311,26 @@ private IAggregate GetStatsAggregate(JsonReader reader, JsonSerializer serialize
311311
if (reader.TokenType == JsonToken.EndObject) return new GeoCentroidAggregate { Count = count };
312312

313313
reader.Read();
314-
var min = reader.Value as double?;
314+
var min = reader.TokenType == JsonToken.Integer
315+
? reader.Value as long?
316+
: reader.Value as double?;
315317
reader.Read();
316318
reader.Read();
317-
var max = reader.Value as double?;
319+
var max = reader.TokenType == JsonToken.Integer
320+
? reader.Value as long?
321+
: reader.Value as double?;
318322
reader.Read();
319323
reader.Read();
320-
var average = reader.Value as double?;
324+
var average = reader.TokenType == JsonToken.Integer
325+
? reader.Value as long?
326+
: reader.Value as double?;
321327
reader.Read();
322328
reader.Read();
323-
var sum = reader.Value as double?;
329+
var sum = reader.TokenType == JsonToken.Integer
330+
? reader.Value as long?
331+
: reader.Value as double?;
324332

325-
var statsMetric = new StatsAggregate()
333+
var statsMetric = new StatsAggregate
326334
{
327335
Average = average,
328336
Count = count,
@@ -336,8 +344,7 @@ private IAggregate GetStatsAggregate(JsonReader reader, JsonSerializer serialize
336344
if (reader.TokenType == JsonToken.EndObject)
337345
return statsMetric;
338346

339-
var propertyName = (string)reader.Value;
340-
while (reader.TokenType != JsonToken.EndObject && propertyName.Contains(Parser.AsStringSuffix))
347+
while (reader.TokenType != JsonToken.EndObject && ((string)reader.Value).EndsWith(Parser.AsStringSuffix))
341348
{
342349
reader.Read();
343350
reader.Read();
@@ -351,7 +358,7 @@ private IAggregate GetStatsAggregate(JsonReader reader, JsonSerializer serialize
351358

352359
private IAggregate GetExtendedStatsAggregate(StatsAggregate statsMetric, JsonReader reader)
353360
{
354-
var extendedStatsMetric = new ExtendedStatsAggregate()
361+
var extendedStatsMetric = new ExtendedStatsAggregate
355362
{
356363
Average = statsMetric.Average,
357364
Count = statsMetric.Count,
@@ -361,24 +368,28 @@ private IAggregate GetExtendedStatsAggregate(StatsAggregate statsMetric, JsonRea
361368
};
362369

363370
reader.Read();
364-
extendedStatsMetric.SumOfSquares = reader.Value as double?;
371+
extendedStatsMetric.SumOfSquares = reader.TokenType == JsonToken.Integer
372+
? reader.Value as long?
373+
: reader.Value as double?;
365374
reader.Read();
366375
reader.Read();
367-
extendedStatsMetric.Variance = reader.Value as double?;
376+
extendedStatsMetric.Variance = reader.TokenType == JsonToken.Integer
377+
? reader.Value as long?
378+
: reader.Value as double?;
368379
reader.Read();
369380
reader.Read();
370-
extendedStatsMetric.StdDeviation = reader.Value as double?;
381+
extendedStatsMetric.StdDeviation = reader.TokenType == JsonToken.Integer
382+
? reader.Value as long?
383+
: reader.Value as double?;
371384
reader.Read();
372385

373-
string propertyName;
374-
375386
if (reader.TokenType != JsonToken.EndObject)
376387
{
377388
var bounds = new StandardDeviationBounds();
378389
reader.Read();
379390
reader.Read();
380391

381-
propertyName = (string)reader.Value;
392+
var propertyName = (string)reader.Value;
382393
if (propertyName == Parser.Upper)
383394
{
384395
reader.Read();
@@ -397,11 +408,10 @@ private IAggregate GetExtendedStatsAggregate(StatsAggregate statsMetric, JsonRea
397408
reader.Read();
398409
}
399410

400-
propertyName = (string)reader.Value;
401-
while (reader.TokenType != JsonToken.EndObject && propertyName.Contains(Parser.AsStringSuffix))
411+
while (reader.TokenType != JsonToken.EndObject && ((string)reader.Value).EndsWith(Parser.AsStringSuffix))
402412
{
403413
// std_deviation_bounds is an object, so we need to skip its properties
404-
if (propertyName.Equals(Parser.StdDeviationBoundsAsString))
414+
if (((string)reader.Value).Equals(Parser.StdDeviationBoundsAsString))
405415
{
406416
reader.Read();
407417
reader.Read();
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using System;
2+
using System.Text;
3+
using Elastic.Xunit.XunitPlumbing;
4+
using Elasticsearch.Net;
5+
using FluentAssertions;
6+
using Nest;
7+
8+
namespace Tests.Reproduce
9+
{
10+
public class GithubIssue4013
11+
{
12+
[U]
13+
public void CanDeserializeExtendedStats()
14+
{
15+
var json = @"{
16+
""took"" : 1,
17+
""timed_out"" : false,
18+
""_shards"" : {
19+
""total"" : 2,
20+
""successful"" : 2,
21+
""skipped"" : 0,
22+
""failed"" : 0
23+
},
24+
""hits"" : {
25+
""total"" : 1100,
26+
""max_score"" : 0.0,
27+
""hits"" : [ ]
28+
},
29+
""aggregations"": {
30+
""extended_stats#1"": {
31+
""count"": 3,
32+
""min"": 1569521764937,
33+
""max"": 1569526264937,
34+
""avg"": 1569524464937,
35+
""sum"": 4708573394811,
36+
""min_as_string"": ""2019-09-26T18:16:04.937Z"",
37+
""max_as_string"": ""2019-09-26T19:31:04.937Z"",
38+
""avg_as_string"": ""2019-09-26T19:01:04.937Z"",
39+
""sum_as_string"": ""2119-03-18T09:03:14.811Z"",
40+
""sum_of_squares"": 7.390221138118668e+24,
41+
""variance"": 3779929134421.3335,
42+
""std_deviation"": 1944203.9847766317,
43+
""std_deviation_bounds"": {
44+
""upper"": 1569528353344.9695,
45+
""lower"": 1569520576529.0305
46+
},
47+
""sum_of_squares_as_string"": ""292278994-08-17T07:12:55.807Z"",
48+
""variance_as_string"": ""2089-10-12T04:18:54.421Z"",
49+
""std_deviation_as_string"": ""1970-01-01T00:32:24.203Z"",
50+
""std_deviation_bounds_as_string"": {
51+
""upper"": ""2019-09-26T20:05:53.344Z"",
52+
""lower"": ""2019-09-26T17:56:16.529Z""
53+
}
54+
}
55+
}
56+
}";
57+
58+
var bytes = Encoding.UTF8.GetBytes(json);
59+
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
60+
var connectionSettings = new ConnectionSettings(pool, new InMemoryConnection(bytes));
61+
var client = new ElasticClient(connectionSettings);
62+
63+
Action searchResponse = () => client.Search<object>(s => s.AllIndices());
64+
65+
searchResponse.ShouldNotThrow();
66+
67+
var response = client.Search<object>(s => s.AllIndices());
68+
69+
var extendedStats = response.Aggregations.ExtendedStats("1");
70+
extendedStats.Should().NotBeNull();
71+
extendedStats.Count.Should().Be(3);
72+
extendedStats.Min.Should().Be(1569521764937);
73+
extendedStats.Max.Should().Be(1569526264937);
74+
extendedStats.Average.Should().Be(1569524464937);
75+
extendedStats.Sum.Should().Be(4708573394811);
76+
extendedStats.SumOfSquares.Should().Be(7.390221138118668e+24);
77+
extendedStats.Variance.Should().Be(3779929134421.3335);
78+
extendedStats.StdDeviation.Should().Be(1944203.9847766317);
79+
extendedStats.StdDeviationBounds.Should().NotBeNull();
80+
extendedStats.StdDeviationBounds.Upper.Should().Be(1569528353344.9695);
81+
extendedStats.StdDeviationBounds.Lower.Should().Be(1569520576529.0305);
82+
}
83+
}
84+
}

0 commit comments

Comments
 (0)