Skip to content

Commit d72cd28

Browse files
committed
Fix #1160: sort values on search failing round trip serialization
1 parent 74a9a5b commit d72cd28

File tree

3 files changed

+129
-16
lines changed

3 files changed

+129
-16
lines changed

src/Nest/DSL/Search/SortGeoDistanceDescriptor.cs

+15-8
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ public interface IGeoDistanceSort : ISort, ICustomJson
1919

2020
public class GeoDistanceSort : SortBase, IGeoDistanceSort
2121
{
22+
internal static List<string> Params = new List<string> { "missing", "mode", "order", "unit" };
23+
24+
internal static int MissingIndex = 0;
25+
internal static int ModeIndex = 1;
26+
internal static int OrderIndex = 2;
27+
internal static int UnitIndex = 3;
28+
2229
public PropertyPathMarker Field { get; set; }
2330
public string PinLocation { get; set; }
2431
public IEnumerable<string> Points { get; set; }
@@ -30,10 +37,10 @@ object ICustomJson.GetCustomJson()
3037
return new Dictionary<object, object>
3138
{
3239
{ this.Field, sort },
33-
{ "missing", this.Missing },
34-
{ "mode", this.Mode },
35-
{ "order", this.Order },
36-
{ "unit", this.GeoUnit }
40+
{ Params[MissingIndex], this.Missing },
41+
{ Params[ModeIndex], this.Mode},
42+
{ Params[OrderIndex], this.Order },
43+
{ Params[UnitIndex], this.GeoUnit }
3744
};
3845
}
3946
}
@@ -119,10 +126,10 @@ object ICustomJson.GetCustomJson()
119126
return new Dictionary<object, object>
120127
{
121128
{ Self.Field, sort },
122-
{ "missing", Self.Missing },
123-
{ "mode", Self.Mode},
124-
{ "order", Self.Order },
125-
{ "unit", Self.GeoUnit }
129+
{ GeoDistanceSort.Params[GeoDistanceSort.MissingIndex], Self.Missing },
130+
{ GeoDistanceSort.Params[GeoDistanceSort.ModeIndex], Self.Mode},
131+
{ GeoDistanceSort.Params[GeoDistanceSort.OrderIndex], Self.Order },
132+
{ GeoDistanceSort.Params[GeoDistanceSort.UnitIndex], Self.GeoUnit }
126133
};
127134
}
128135
}

src/Nest/Resolvers/Converters/SortCollectionConverter.cs

+76-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using Newtonsoft.Json;
1+
using Nest.DSL.Descriptors;
2+
using Newtonsoft.Json;
3+
using Newtonsoft.Json.Linq;
24
using System;
35
using System.Collections.Generic;
46
using System.Linq;
@@ -13,14 +15,59 @@ public override bool CanConvert(Type objectType)
1315
return typeof(IList<KeyValuePair<PropertyPathMarker, ISort>>).IsAssignableFrom(objectType);
1416
}
1517

16-
public override bool CanRead
17-
{
18-
get { return false; }
19-
}
20-
2118
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
2219
{
23-
return new InvalidOperationException();
20+
var sorts = new List<KeyValuePair<PropertyPathMarker, ISort>>();
21+
while (reader.TokenType != JsonToken.EndArray)
22+
{
23+
reader.Read();
24+
if (reader.TokenType == JsonToken.EndArray)
25+
break;
26+
reader.Read();
27+
var field = reader.Value as string;
28+
reader.Read();
29+
30+
if (field == "_geo_distance")
31+
{
32+
var j = JObject.Load(reader);
33+
if (j != null)
34+
{
35+
var sort = j.ToObject<GeoDistanceSort>(serializer);
36+
if (sort != null)
37+
{
38+
LoadGeoDistanceSortLocation(sort, j);
39+
sorts.Add(new KeyValuePair<PropertyPathMarker, ISort>("_geo_distance", sort));
40+
}
41+
}
42+
}
43+
else if (field == "_script")
44+
{
45+
var j = JObject.Load(reader);
46+
if (j != null)
47+
{
48+
var sort = j.ToObject<ScriptSort>(serializer);
49+
if (sort != null)
50+
{
51+
sorts.Add(new KeyValuePair<PropertyPathMarker, ISort>("_script", sort));
52+
}
53+
}
54+
}
55+
else
56+
{
57+
var j = JObject.Load(reader);
58+
if (j != null)
59+
{
60+
var sort = j.ToObject<Sort>(serializer);
61+
if (sort != null)
62+
{
63+
sort.Field = field;
64+
sorts.Add(new KeyValuePair<PropertyPathMarker, ISort>(sort.Field, sort));
65+
}
66+
}
67+
}
68+
reader.Read();
69+
}
70+
return sorts;
2471
}
2572

2673
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
@@ -38,5 +85,27 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s
3885
}
3986
writer.WriteEndArray();
4087
}
88+
89+
private void LoadGeoDistanceSortLocation(GeoDistanceSort sort, JObject j)
90+
{
91+
var field = j.Properties().Where(p => !GeoDistanceSort.Params.Contains(p.Name)).FirstOrDefault();
92+
93+
if (field != null)
94+
{
95+
sort.Field = field.Name;
96+
97+
try
98+
{
99+
sort.PinLocation = field.Value.Value<string>();
100+
}
101+
catch { }
102+
103+
try
104+
{
105+
sort.Points = field.Value.Value<IEnumerable<string>>();
106+
}
107+
catch { }
108+
}
109+
}
41110
}
42111
}

src/Tests/Nest.Tests.Unit/Search/Sorting/SortTests.cs

+38-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
using System.Reflection;
1+
using FluentAssertions;
2+
using System.Reflection;
23
using NUnit.Framework;
34
using Nest.Tests.MockData.Domain;
5+
using System.Text;
6+
using System.IO;
47

58
namespace Nest.Tests.Unit.Search.Sorting
69
{
@@ -439,5 +442,39 @@ public void RandomScriptSort()
439442
);
440443
this.JsonEquals(s, MethodInfo.GetCurrentMethod());
441444
}
445+
446+
[Test]
447+
public void SortSerializeThenDeserializeTest()
448+
{
449+
var d1 = new SearchDescriptor<ElasticsearchProject>()
450+
.From(0)
451+
.Size(20)
452+
.MatchAll()
453+
.Sort(s => s
454+
.OnField(p => p.Id)
455+
.Order(SortOrder.Ascending)
456+
)
457+
.SortGeoDistance(s => s
458+
.OnField(p => p.Origin)
459+
.PinTo(40, 70)
460+
)
461+
.SortScript(s => s
462+
.Ascending()
463+
.Script("(doc['_id'].stringValue + salt).hashCode()")
464+
.Params(p => p
465+
.Add("salt", "some_random_string")
466+
)
467+
.Type("number")
468+
);
469+
470+
var s1 = this._client.Serializer.Serialize(d1);
471+
var d2 = this._client.Serializer.Deserialize<SearchDescriptor<ElasticsearchProject>>(new MemoryStream(s1));
472+
var s2 = this._client.Serializer.Serialize(d2);
473+
474+
var s1Json = Encoding.UTF8.GetString(s1);
475+
var s2Json = Encoding.UTF8.GetString(s2);
476+
477+
s1Json.JsonEquals(s2Json).Should().BeTrue();
478+
}
442479
}
443480
}

0 commit comments

Comments
 (0)