Skip to content

Commit 2bf40fe

Browse files
Sort simplification (#6824) (#6826)
* Code-gen updated to simplify away SortCombinations * Prefer type deserialization rather than activator utilities on SingleOrManySerializationHelper * Add manual converter for FieldSort until shortcut properties are code-generated. * Manual converter for SortOptions to handle union variations of SortCombinations * Add tests for SortOptions serialization Co-authored-by: Steve Gordon <sgordon@hotmail.co.uk>
1 parent ca7351d commit 2bf40fe

19 files changed

+405
-254
lines changed

src/Elastic.Clients.Elasticsearch/Serialization/SingleOrManySerializationHelper.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ public static IEnumerable<TItem> Deserialize<TItem>(ref Utf8JsonReader reader, J
3737
// }
3838
if (reader.TokenType == JsonTokenType.String)
3939
{
40-
var value = reader.GetString();
41-
var item = (TItem)Activator.CreateInstance(typeof(TItem), value);
40+
var item = (TItem)JsonSerializer.Deserialize(ref reader, typeof(TItem), options);
4241
return new TItem[] { item };
4342
}
4443

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Text.Json;
7+
using System.Text.Json.Serialization;
8+
using Elastic.Clients.Elasticsearch.Mapping;
9+
10+
namespace Elastic.Clients.Elasticsearch;
11+
12+
[JsonConverter(typeof(FieldSortConverter))]
13+
public partial class FieldSort
14+
{
15+
public static FieldSort Empty { get; } = new();
16+
}
17+
18+
internal sealed class FieldSortConverter : JsonConverter<FieldSort>
19+
{
20+
// This is temporarily a manual converter until we code-gen for shortcut properties.
21+
// This serves as the template for those converters.
22+
23+
public override FieldSort? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
24+
{
25+
if (reader.TokenType == JsonTokenType.StartObject)
26+
{
27+
string? format = null;
28+
FieldValue? missing = null;
29+
SortMode? mode = null;
30+
NestedSortValue? nested = null;
31+
FieldSortNumericType? numericType = null;
32+
SortOrder? order = null;
33+
FieldType? unmappedType = null;
34+
35+
while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
36+
{
37+
if (reader.TokenType == JsonTokenType.PropertyName)
38+
{
39+
var propertyName = reader.GetString();
40+
reader.Read();
41+
42+
switch (propertyName)
43+
{
44+
case "format":
45+
format = reader.GetString();
46+
break;
47+
case "missing":
48+
missing = JsonSerializer.Deserialize<FieldValue>(ref reader, options);
49+
break;
50+
case "mode":
51+
mode = JsonSerializer.Deserialize<SortMode>(ref reader, options);
52+
break;
53+
case "nested":
54+
nested = JsonSerializer.Deserialize<NestedSortValue>(ref reader, options);
55+
break;
56+
case "numeric_type":
57+
numericType = JsonSerializer.Deserialize<FieldSortNumericType>(ref reader, options);
58+
break;
59+
case "order":
60+
order = JsonSerializer.Deserialize<SortOrder>(ref reader, options);
61+
break;
62+
case "unmapped_type":
63+
unmappedType = JsonSerializer.Deserialize<FieldType>(ref reader, options);
64+
break;
65+
default:
66+
throw new JsonException("Unexpected property while reading `Field`.");
67+
}
68+
}
69+
}
70+
71+
return new FieldSort
72+
{
73+
Format = format,
74+
Missing = missing,
75+
Mode = mode,
76+
Nested = nested,
77+
NumericType = numericType,
78+
Order = order,
79+
UnmappedType = unmappedType
80+
};
81+
}
82+
83+
else if (reader.TokenType == JsonTokenType.String) // Shortcut property
84+
{
85+
var sortOrder = JsonSerializer.Deserialize<SortOrder>(ref reader, options);
86+
return new FieldSort { Order = sortOrder };
87+
}
88+
89+
throw new JsonException($"Unexpected JSON token '{reader.TokenType}' encountered while deserializing FieldSort.");
90+
}
91+
92+
public override void Write(Utf8JsonWriter writer, FieldSort value, JsonSerializerOptions options)
93+
{
94+
if (value is null)
95+
{
96+
writer.WriteNullValue();
97+
return;
98+
}
99+
100+
writer.WriteStartObject();
101+
102+
if (value.Format is not null)
103+
{
104+
writer.WritePropertyName("format");
105+
writer.WriteStringValue(value.Format);
106+
}
107+
108+
if (value.Missing.HasValue)
109+
{
110+
writer.WritePropertyName("missing");
111+
JsonSerializer.Serialize(writer, value.Missing.Value, options);
112+
}
113+
114+
if (value.Mode.HasValue)
115+
{
116+
writer.WritePropertyName("mode");
117+
JsonSerializer.Serialize(writer, value.Mode.Value, options);
118+
}
119+
120+
if (value.Nested is not null)
121+
{
122+
writer.WritePropertyName("nested");
123+
JsonSerializer.Serialize(writer, value.Nested, options);
124+
}
125+
126+
if (value.NumericType.HasValue)
127+
{
128+
writer.WritePropertyName("numeric_type");
129+
JsonSerializer.Serialize(writer, value.NumericType.Value, options);
130+
}
131+
132+
if (value.Order.HasValue)
133+
{
134+
writer.WritePropertyName("order");
135+
JsonSerializer.Serialize(writer, value.Order.Value, options);
136+
}
137+
138+
if (value.UnmappedType.HasValue)
139+
{
140+
writer.WritePropertyName("unmapped_type");
141+
JsonSerializer.Serialize(writer, value.UnmappedType.Value, options);
142+
}
143+
144+
writer.WriteEndObject();
145+
}
146+
}

src/Elastic.Clients.Elasticsearch/Types/SortCombinations.cs

-12
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Text.Json;
7+
using System.Text.Json.Serialization;
8+
using Elastic.Clients.Elasticsearch.Serialization;
9+
using Elastic.Transport;
10+
11+
namespace Elastic.Clients.Elasticsearch;
12+
13+
public partial class SortOptions
14+
{
15+
public static SortOptions Field(Field field) => new(field, FieldSort.Empty);
16+
}
17+
18+
internal sealed class SortOptionsConverter : JsonConverter<SortOptions>
19+
{
20+
// We manually define this converter since we simplify SortCombinations union from the spec as SortOptions instance.
21+
// This requires a custom read method to handle deserialisation of the potential union JSON as specified.
22+
23+
public override SortOptions Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
24+
{
25+
if (reader.TokenType == JsonTokenType.StartObject)
26+
{
27+
reader.Read();
28+
if (reader.TokenType != JsonTokenType.PropertyName)
29+
{
30+
throw new JsonException("Expected a property name token representing the variant held within this container.");
31+
}
32+
33+
var propertyName = reader.GetString();
34+
reader.Read();
35+
if (propertyName == "_doc")
36+
{
37+
var variant = JsonSerializer.Deserialize<ScoreSort?>(ref reader, options);
38+
reader.Read();
39+
return new SortOptions(propertyName, variant);
40+
}
41+
42+
if (propertyName == "_score")
43+
{
44+
var variant = JsonSerializer.Deserialize<ScoreSort?>(ref reader, options);
45+
reader.Read();
46+
return new SortOptions(propertyName, variant);
47+
}
48+
49+
if (propertyName == "_script")
50+
{
51+
var variant = JsonSerializer.Deserialize<ScriptSort?>(ref reader, options);
52+
reader.Read();
53+
return new SortOptions(propertyName, variant);
54+
}
55+
56+
// For field sorts, the property name will be the field name
57+
{
58+
var variant = JsonSerializer.Deserialize<FieldSort>(ref reader, options);
59+
reader.Read();
60+
return new SortOptions(propertyName, variant);
61+
}
62+
}
63+
64+
else if (reader.TokenType == JsonTokenType.String)
65+
{
66+
var fieldName = reader.GetString();
67+
return SortOptions.Field(fieldName, FieldSort.Empty);
68+
}
69+
70+
throw new JsonException($"Unexpected JSON token '{reader.TokenType}' encountered while deserializing SortOptions.");
71+
}
72+
73+
public override void Write(Utf8JsonWriter writer, SortOptions value, JsonSerializerOptions options)
74+
{
75+
if (!options.TryGetClientSettings(out var settings))
76+
throw new JsonException("Unable to retrieve IElasticsearchClientSettings.");
77+
78+
string? fieldName = null;
79+
80+
if (value.AdditionalPropertyName is IUrlParameter urlParameter)
81+
{
82+
fieldName = urlParameter.GetString(settings);
83+
}
84+
85+
// Special handling for shortcut on sorting with a basic field sort
86+
if (value.Variant.Equals(FieldSort.Empty))
87+
{
88+
writer.WriteStringValue(fieldName ?? value.VariantName);
89+
return;
90+
}
91+
92+
writer.WriteStartObject();
93+
94+
writer.WritePropertyName(fieldName ?? value.VariantName);
95+
96+
switch (value.VariantName)
97+
{
98+
case "_doc":
99+
JsonSerializer.Serialize<ScoreSort>(writer, (ScoreSort)value.Variant, options);
100+
break;
101+
case "_score":
102+
JsonSerializer.Serialize<ScoreSort>(writer, (ScoreSort)value.Variant, options);
103+
break;
104+
case "_script":
105+
JsonSerializer.Serialize<ScriptSort>(writer, (ScriptSort)value.Variant, options);
106+
break;
107+
default:
108+
JsonSerializer.Serialize<FieldSort>(writer, (FieldSort)value.Variant, options);
109+
break;
110+
}
111+
112+
writer.WriteEndObject();
113+
}
114+
}

src/Elastic.Clients.Elasticsearch/_Generated/Api/AsyncSearch/AsyncSearchSubmitRequest.g.cs

+8-8
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ public override AsyncSearchSubmitRequest Read(ref Utf8JsonReader reader, Type ty
254254

255255
if (property == "sort")
256256
{
257-
variant.Sort = JsonSerializer.Deserialize<IEnumerable<Elastic.Clients.Elasticsearch.SortCombinations>?>(ref reader, options);
257+
variant.Sort = JsonSerializer.Deserialize<IEnumerable<Elastic.Clients.Elasticsearch.SortOptions>?>(ref reader, options);
258258
continue;
259259
}
260260

@@ -723,7 +723,7 @@ public AsyncSearchSubmitRequest(Elastic.Clients.Elasticsearch.Indices? indices)
723723
[JsonInclude]
724724
[JsonPropertyName("sort")]
725725
[JsonConverter(typeof(SortConverter))]
726-
public IEnumerable<Elastic.Clients.Elasticsearch.SortCombinations>? Sort { get; set; }
726+
public IEnumerable<Elastic.Clients.Elasticsearch.SortOptions>? Sort { get; set; }
727727

728728
[JsonInclude]
729729
[JsonPropertyName("_source")]
@@ -925,7 +925,7 @@ public AsyncSearchSubmitRequestDescriptor<TDocument> Indices(Elastic.Clients.Ela
925925

926926
private int? SizeValue { get; set; }
927927

928-
private IEnumerable<Elastic.Clients.Elasticsearch.SortCombinations>? SortValue { get; set; }
928+
private IEnumerable<Elastic.Clients.Elasticsearch.SortOptions>? SortValue { get; set; }
929929

930930
private IEnumerable<string>? StatsValue { get; set; }
931931

@@ -1319,7 +1319,7 @@ public AsyncSearchSubmitRequestDescriptor<TDocument> Size(int? size)
13191319
return Self;
13201320
}
13211321

1322-
public AsyncSearchSubmitRequestDescriptor<TDocument> Sort(IEnumerable<Elastic.Clients.Elasticsearch.SortCombinations>? sort)
1322+
public AsyncSearchSubmitRequestDescriptor<TDocument> Sort(IEnumerable<Elastic.Clients.Elasticsearch.SortOptions>? sort)
13231323
{
13241324
SortValue = sort;
13251325
return Self;
@@ -1690,7 +1690,7 @@ protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions o
16901690
if (SortValue is not null)
16911691
{
16921692
writer.WritePropertyName("sort");
1693-
SingleOrManySerializationHelper.Serialize<Elastic.Clients.Elasticsearch.SortCombinations>(SortValue, writer, options);
1693+
SingleOrManySerializationHelper.Serialize<Elastic.Clients.Elasticsearch.SortOptions>(SortValue, writer, options);
16941694
}
16951695

16961696
if (StatsValue is not null)
@@ -1899,7 +1899,7 @@ public AsyncSearchSubmitRequestDescriptor Indices(Elastic.Clients.Elasticsearch.
18991899

19001900
private int? SizeValue { get; set; }
19011901

1902-
private IEnumerable<Elastic.Clients.Elasticsearch.SortCombinations>? SortValue { get; set; }
1902+
private IEnumerable<Elastic.Clients.Elasticsearch.SortOptions>? SortValue { get; set; }
19031903

19041904
private IEnumerable<string>? StatsValue { get; set; }
19051905

@@ -2293,7 +2293,7 @@ public AsyncSearchSubmitRequestDescriptor Size(int? size)
22932293
return Self;
22942294
}
22952295

2296-
public AsyncSearchSubmitRequestDescriptor Sort(IEnumerable<Elastic.Clients.Elasticsearch.SortCombinations>? sort)
2296+
public AsyncSearchSubmitRequestDescriptor Sort(IEnumerable<Elastic.Clients.Elasticsearch.SortOptions>? sort)
22972297
{
22982298
SortValue = sort;
22992299
return Self;
@@ -2664,7 +2664,7 @@ protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions o
26642664
if (SortValue is not null)
26652665
{
26662666
writer.WritePropertyName("sort");
2667-
SingleOrManySerializationHelper.Serialize<Elastic.Clients.Elasticsearch.SortCombinations>(SortValue, writer, options);
2667+
SingleOrManySerializationHelper.Serialize<Elastic.Clients.Elasticsearch.SortOptions>(SortValue, writer, options);
26682668
}
26692669

26702670
if (StatsValue is not null)

0 commit comments

Comments
 (0)