From dcb0ab2b411f851613eb65bd2d3ce3700330a931 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Mon, 4 Jan 2021 11:03:24 +0000 Subject: [PATCH] Fix deserialisation of aggs in Translate response The Translate API in elasticsearch returns aggregations using the key "aggregations" rather than "aggs". This results in aggregations not appearing in the SearchRequest instance. This fix adds a field so that aggregations deserialise correctly using UTF8Json. --- src/Nest/Aggregations/AggregationContainer.cs | 10 +++- src/Nest/Search/Search/SearchRequest.cs | 9 +++- tests/Tests.Reproduce/GithubIssue5201.cs | 54 +++++++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 tests/Tests.Reproduce/GithubIssue5201.cs diff --git a/src/Nest/Aggregations/AggregationContainer.cs b/src/Nest/Aggregations/AggregationContainer.cs index 3bcbd3e6333..31c7e054a58 100644 --- a/src/Nest/Aggregations/AggregationContainer.cs +++ b/src/Nest/Aggregations/AggregationContainer.cs @@ -294,7 +294,15 @@ public class AggregationContainer : IAggregationContainer { public IAdjacencyMatrixAggregation AdjacencyMatrix { get; set; } - public AggregationDictionary Aggregations { get; set; } + // This is currently used to support deserializing the response from SQL Translate, + // which forms a response which uses "aggregations", rather than "aggs". Longer term + // it would be preferred to address that in Elasticsearch itself. + [DataMember(Name = "aggregations")] + private AggregationDictionary _aggs; + + // ReSharper disable once ConvertToAutoProperty + public AggregationDictionary Aggregations { get => _aggs; set => _aggs = value; } + public IAverageAggregation Average { get; set; } public IAverageBucketAggregation AverageBucket { get; set; } diff --git a/src/Nest/Search/Search/SearchRequest.cs b/src/Nest/Search/Search/SearchRequest.cs index fb63c469458..57fa5f86acf 100644 --- a/src/Nest/Search/Search/SearchRequest.cs +++ b/src/Nest/Search/Search/SearchRequest.cs @@ -179,8 +179,15 @@ public partial interface ISearchRequest : ISearchRequest { } [DataContract] public partial class SearchRequest { + // This is currently used to support deserializing the response from SQL Translate, + // which forms a response which uses "aggregations", rather than "aggs". Longer term + // it would be preferred to address that in Elasticsearch itself. + [DataMember(Name = "aggregations")] + private AggregationDictionary _aggs; + /// - public AggregationDictionary Aggregations { get; set; } + // ReSharper disable once ConvertToAutoProperty + public AggregationDictionary Aggregations { get => _aggs; set => _aggs = value; } /// public IFieldCollapse Collapse { get; set; } /// diff --git a/tests/Tests.Reproduce/GithubIssue5201.cs b/tests/Tests.Reproduce/GithubIssue5201.cs new file mode 100644 index 00000000000..b1950918dc9 --- /dev/null +++ b/tests/Tests.Reproduce/GithubIssue5201.cs @@ -0,0 +1,54 @@ +// Licensed to Elasticsearch B.V under one or more agreements. +// Elasticsearch B.V licenses this file to you under the Apache 2.0 License. +// See the LICENSE file in the project root for more information + +using System; +using System.Text; +using System.Threading.Tasks; +using Elastic.Elasticsearch.Xunit.XunitPlumbing; +using Elasticsearch.Net; +using FluentAssertions; +using Nest; + +namespace Tests.Reproduce +{ + public class GitHubIssue5201 + { + private static readonly byte[] ResponseBytes = Encoding.UTF8.GetBytes(@"{ + ""size"" : 0, + ""_source"" : false, + ""stored_fields"" : ""_none_"", + ""aggregations"" : { + ""groupby"" : { + ""composite"" : { + ""size"" : 1000, + ""sources"" : [ + { + ""ccf51bfa"" : { + ""terms"" : { + ""field"" : ""id"", + ""missing_bucket"" : true, + ""order"" : ""asc"" + } + } + } + ] + } + } + } + }"); + + [U] public async Task DeserializeAggregations() + { + var pool = new SingleNodeConnectionPool(new Uri($"http://localhost:9200")); + var settings = new ConnectionSettings(pool, new InMemoryConnection(ResponseBytes)); + var client = new ElasticClient(settings); + + var translateResponseAsync = await client.Sql.TranslateAsync(t => t.Query("select UDFvarchar1, count(1) from interactions group by UDFvarchar1 order by UDFvarchar1")); + translateResponseAsync.Result.Aggregations.Should().NotBeNull(); + + var translateResponse = client.Sql.Translate(t => t.Query("select UDFvarchar1, count(1) from interactions group by UDFvarchar1 order by UDFvarchar1")); + translateResponse.Result.Aggregations.Should().NotBeNull(); + } + } +}