Skip to content
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

[Backport 7.x] Deserialize sort short forms #4830

Merged
merged 1 commit into from
Jun 30, 2020
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
107 changes: 67 additions & 40 deletions src/Nest/CommonOptions/Sorting/SortFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,55 +22,82 @@ public ISort Deserialize(ref JsonReader reader, IJsonFormatterResolver formatter
{
ISort sort = null;

var count = 0;
while (reader.ReadIsInObject(ref count))
switch (reader.GetCurrentJsonToken())
{
var sortProperty = reader.ReadPropertyNameSegmentRaw();
if (SortFields.TryGetValue(sortProperty, out var value))
case JsonToken.String:
{
switch (value)
var sortProperty = reader.ReadString();
sort = new FieldSort { Field = sortProperty };
break;
}
case JsonToken.BeginObject:
{
var count = 0;
while (reader.ReadIsInObject(ref count))
{
case 0:
var propCount = 0;
string field = null;
var geoDistanceSegment = reader.ReadNextBlockSegment();
var geoDistanceReader = new JsonReader(geoDistanceSegment.Array, geoDistanceSegment.Offset);
IEnumerable<GeoLocation> points = null;
while (geoDistanceReader.ReadIsInObject(ref propCount))
var sortProperty = reader.ReadPropertyNameSegmentRaw();
if (SortFields.TryGetValue(sortProperty, out var value))
{
switch (value)
{
var nameSegment = geoDistanceReader.ReadPropertyNameSegmentRaw();
if (geoDistanceReader.GetCurrentJsonToken() == JsonToken.BeginArray)
{
field = nameSegment.Utf8String();
points = formatterResolver.GetFormatter<IEnumerable<GeoLocation>>()
case 0:
var propCount = 0;
string field = null;
var geoDistanceSegment = reader.ReadNextBlockSegment();
var geoDistanceReader = new JsonReader(geoDistanceSegment.Array, geoDistanceSegment.Offset);
IEnumerable<GeoLocation> points = null;
while (geoDistanceReader.ReadIsInObject(ref propCount))
{
var nameSegment = geoDistanceReader.ReadPropertyNameSegmentRaw();
if (geoDistanceReader.GetCurrentJsonToken() == JsonToken.BeginArray)
{
field = nameSegment.Utf8String();
points = formatterResolver.GetFormatter<IEnumerable<GeoLocation>>()
.Deserialize(ref geoDistanceReader, formatterResolver);
break;
}

// skip value if not array
geoDistanceReader.ReadNextBlock();
}
geoDistanceReader = new JsonReader(geoDistanceSegment.Array, geoDistanceSegment.Offset);
var geoDistanceSort = formatterResolver.GetFormatter<GeoDistanceSort>()
.Deserialize(ref geoDistanceReader, formatterResolver);
geoDistanceSort.Field = field;
geoDistanceSort.Points = points;
sort = geoDistanceSort;
break;
}

// skip value if not array
geoDistanceReader.ReadNextBlock();
case 1:
sort = formatterResolver.GetFormatter<ScriptSort>()
.Deserialize(ref reader, formatterResolver);
break;
}
}
else
{
var field = sortProperty.Utf8String();
FieldSort sortField;
if (reader.GetCurrentJsonToken() == JsonToken.String)
{
var sortOrder = formatterResolver.GetFormatter<SortOrder>()
.Deserialize(ref reader, formatterResolver);
sortField = new FieldSort { Field = field, Order = sortOrder };
}
geoDistanceReader = new JsonReader(geoDistanceSegment.Array, geoDistanceSegment.Offset);
var geoDistanceSort = formatterResolver.GetFormatter<GeoDistanceSort>()
.Deserialize(ref geoDistanceReader, formatterResolver);
geoDistanceSort.Field = field;
geoDistanceSort.Points = points;
sort = geoDistanceSort;
break;
case 1:
sort = formatterResolver.GetFormatter<ScriptSort>()
.Deserialize(ref reader, formatterResolver);
break;
else
{
sortField = formatterResolver.GetFormatter<FieldSort>()
.Deserialize(ref reader, formatterResolver);
sortField.Field = field;
}

sort = sortField;
}
}

break;
}
else
{
var field = sortProperty.Utf8String();
var sortField = formatterResolver.GetFormatter<FieldSort>()
.Deserialize(ref reader, formatterResolver);
sortField.Field = field;
sort = sortField;
}
default:
throw new JsonParsingException($"Cannot deserialize {nameof(ISort)} from {reader.GetCurrentJsonToken()}");
}

return sort;
Expand Down
46 changes: 46 additions & 0 deletions tests/Tests.Reproduce/GitHubIssue4797.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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.Text;
using Elastic.Elasticsearch.Xunit.XunitPlumbing;
using FluentAssertions;
using Nest;
using Tests.Core.Client;

namespace Tests.Reproduce
{
public class GitHubIssue4797
{
[U]
public void DeserializeSortWithOnlyFieldAndOrder()
{
var json = @"
{
""sort"" : [
{ ""post_date"" : {""order"" : ""asc""}},
""user"",
{ ""name"" : ""desc"" },
{ ""age"" : ""desc"" },
""_score""
],
""query"" : {
""term"" : { ""user"" : ""kimchy"" }
}
}
";

var bytes = Encoding.UTF8.GetBytes(json);
var client = TestClient.FixedInMemoryClient(bytes);

using var stream = client.ConnectionSettings.MemoryStreamFactory.Create(bytes);
var request = client.RequestResponseSerializer.Deserialize<SearchRequest>(stream);

request.Should().NotBeNull();
request.Sort.Should().NotBeNull().And.HaveCount(5);
request.Sort[1].SortKey.Should().Be("user");
request.Sort[2].SortKey.Should().Be("name");
request.Sort[2].Order.Should().Be(SortOrder.Descending);
}
}
}