From e7a838ce8f8e88c352fd4ed81248a51857f93bc7 Mon Sep 17 00:00:00 2001 From: Steve Gordon Date: Tue, 5 Jan 2021 14:05:30 +0000 Subject: [PATCH] Fix deserialisation of aggs in Translate response (#5228) 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(); + } + } +}