Skip to content

Sort simplification #6824

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

Merged
merged 5 commits into from
Oct 26, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ public static IEnumerable<TItem> Deserialize<TItem>(ref Utf8JsonReader reader, J
// }
if (reader.TokenType == JsonTokenType.String)
{
var value = reader.GetString();
var item = (TItem)Activator.CreateInstance(typeof(TItem), value);
var item = (TItem)JsonSerializer.Deserialize(ref reader, typeof(TItem), options);
return new TItem[] { item };
}

Expand Down
146 changes: 146 additions & 0 deletions src/Elastic.Clients.Elasticsearch/Types/FieldSort.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// 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.Json;
using System.Text.Json.Serialization;
using Elastic.Clients.Elasticsearch.Mapping;

namespace Elastic.Clients.Elasticsearch;

[JsonConverter(typeof(FieldSortConverter))]
public partial class FieldSort
{
public static FieldSort Empty { get; } = new();
}

internal sealed class FieldSortConverter : JsonConverter<FieldSort>
{
// This is temporarily a manual converter until we code-gen for shortcut properties.
// This serves as the template for those converters.

public override FieldSort? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.StartObject)
{
string? format = null;
FieldValue? missing = null;
SortMode? mode = null;
NestedSortValue? nested = null;
FieldSortNumericType? numericType = null;
SortOrder? order = null;
FieldType? unmappedType = null;

while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
var propertyName = reader.GetString();
reader.Read();

switch (propertyName)
{
case "format":
format = reader.GetString();
break;
case "missing":
missing = JsonSerializer.Deserialize<FieldValue>(ref reader, options);
break;
case "mode":
mode = JsonSerializer.Deserialize<SortMode>(ref reader, options);
break;
case "nested":
nested = JsonSerializer.Deserialize<NestedSortValue>(ref reader, options);
break;
case "numeric_type":
numericType = JsonSerializer.Deserialize<FieldSortNumericType>(ref reader, options);
break;
case "order":
order = JsonSerializer.Deserialize<SortOrder>(ref reader, options);
break;
case "unmapped_type":
unmappedType = JsonSerializer.Deserialize<FieldType>(ref reader, options);
break;
default:
throw new JsonException("Unexpected property while reading `Field`.");
}
}
}

return new FieldSort
{
Format = format,
Missing = missing,
Mode = mode,
Nested = nested,
NumericType = numericType,
Order = order,
UnmappedType = unmappedType
};
}

else if (reader.TokenType == JsonTokenType.String) // Shortcut property
{
var sortOrder = JsonSerializer.Deserialize<SortOrder>(ref reader, options);
return new FieldSort { Order = sortOrder };
}

throw new JsonException($"Unexpected JSON token '{reader.TokenType}' encountered while deserializing FieldSort.");
}

public override void Write(Utf8JsonWriter writer, FieldSort value, JsonSerializerOptions options)
{
if (value is null)
{
writer.WriteNullValue();
return;
}

writer.WriteStartObject();

if (value.Format is not null)
{
writer.WritePropertyName("format");
writer.WriteStringValue(value.Format);
}

if (value.Missing.HasValue)
{
writer.WritePropertyName("missing");
JsonSerializer.Serialize(writer, value.Missing.Value, options);
}

if (value.Mode.HasValue)
{
writer.WritePropertyName("mode");
JsonSerializer.Serialize(writer, value.Mode.Value, options);
}

if (value.Nested is not null)
{
writer.WritePropertyName("nested");
JsonSerializer.Serialize(writer, value.Nested, options);
}

if (value.NumericType.HasValue)
{
writer.WritePropertyName("numeric_type");
JsonSerializer.Serialize(writer, value.NumericType.Value, options);
}

if (value.Order.HasValue)
{
writer.WritePropertyName("order");
JsonSerializer.Serialize(writer, value.Order.Value, options);
}

if (value.UnmappedType.HasValue)
{
writer.WritePropertyName("unmapped_type");
JsonSerializer.Serialize(writer, value.UnmappedType.Value, options);
}

writer.WriteEndObject();
}
}
12 changes: 0 additions & 12 deletions src/Elastic.Clients.Elasticsearch/Types/SortCombinations.cs

This file was deleted.

114 changes: 114 additions & 0 deletions src/Elastic.Clients.Elasticsearch/Types/SortOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// 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.Json;
using System.Text.Json.Serialization;
using Elastic.Clients.Elasticsearch.Serialization;
using Elastic.Transport;

namespace Elastic.Clients.Elasticsearch;

public partial class SortOptions
{
public static SortOptions Field(Field field) => new(field, FieldSort.Empty);
}

internal sealed class SortOptionsConverter : JsonConverter<SortOptions>
{
// We manually define this converter since we simplify SortCombinations union from the spec as SortOptions instance.
// This requires a custom read method to handle deserialisation of the potential union JSON as specified.

public override SortOptions Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.StartObject)
{
reader.Read();
if (reader.TokenType != JsonTokenType.PropertyName)
{
throw new JsonException("Expected a property name token representing the variant held within this container.");
}

var propertyName = reader.GetString();
reader.Read();
if (propertyName == "_doc")
{
var variant = JsonSerializer.Deserialize<ScoreSort?>(ref reader, options);
reader.Read();
return new SortOptions(propertyName, variant);
}

if (propertyName == "_score")
{
var variant = JsonSerializer.Deserialize<ScoreSort?>(ref reader, options);
reader.Read();
return new SortOptions(propertyName, variant);
}

if (propertyName == "_script")
{
var variant = JsonSerializer.Deserialize<ScriptSort?>(ref reader, options);
reader.Read();
return new SortOptions(propertyName, variant);
}

// For field sorts, the property name will be the field name
{
var variant = JsonSerializer.Deserialize<FieldSort>(ref reader, options);
reader.Read();
return new SortOptions(propertyName, variant);
}
}

else if (reader.TokenType == JsonTokenType.String)
{
var fieldName = reader.GetString();
return SortOptions.Field(fieldName, FieldSort.Empty);
}

throw new JsonException($"Unexpected JSON token '{reader.TokenType}' encountered while deserializing SortOptions.");
}

public override void Write(Utf8JsonWriter writer, SortOptions value, JsonSerializerOptions options)
{
if (!options.TryGetClientSettings(out var settings))
throw new JsonException("Unable to retrieve IElasticsearchClientSettings.");

string? fieldName = null;

if (value.AdditionalPropertyName is IUrlParameter urlParameter)
{
fieldName = urlParameter.GetString(settings);
}

// Special handling for shortcut on sorting with a basic field sort
if (value.Variant.Equals(FieldSort.Empty))
{
writer.WriteStringValue(fieldName ?? value.VariantName);
return;
}

writer.WriteStartObject();

writer.WritePropertyName(fieldName ?? value.VariantName);

switch (value.VariantName)
{
case "_doc":
JsonSerializer.Serialize<ScoreSort>(writer, (ScoreSort)value.Variant, options);
break;
case "_score":
JsonSerializer.Serialize<ScoreSort>(writer, (ScoreSort)value.Variant, options);
break;
case "_script":
JsonSerializer.Serialize<ScriptSort>(writer, (ScriptSort)value.Variant, options);
break;
default:
JsonSerializer.Serialize<FieldSort>(writer, (FieldSort)value.Variant, options);
break;
}

writer.WriteEndObject();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ public override AsyncSearchSubmitRequest Read(ref Utf8JsonReader reader, Type ty

if (property == "sort")
{
variant.Sort = JsonSerializer.Deserialize<IEnumerable<Elastic.Clients.Elasticsearch.SortCombinations>?>(ref reader, options);
variant.Sort = JsonSerializer.Deserialize<IEnumerable<Elastic.Clients.Elasticsearch.SortOptions>?>(ref reader, options);
continue;
}

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

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

private int? SizeValue { get; set; }

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

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

Expand Down Expand Up @@ -1319,7 +1319,7 @@ public AsyncSearchSubmitRequestDescriptor<TDocument> Size(int? size)
return Self;
}

public AsyncSearchSubmitRequestDescriptor<TDocument> Sort(IEnumerable<Elastic.Clients.Elasticsearch.SortCombinations>? sort)
public AsyncSearchSubmitRequestDescriptor<TDocument> Sort(IEnumerable<Elastic.Clients.Elasticsearch.SortOptions>? sort)
{
SortValue = sort;
return Self;
Expand Down Expand Up @@ -1690,7 +1690,7 @@ protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions o
if (SortValue is not null)
{
writer.WritePropertyName("sort");
SingleOrManySerializationHelper.Serialize<Elastic.Clients.Elasticsearch.SortCombinations>(SortValue, writer, options);
SingleOrManySerializationHelper.Serialize<Elastic.Clients.Elasticsearch.SortOptions>(SortValue, writer, options);
}

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

private int? SizeValue { get; set; }

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

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

Expand Down Expand Up @@ -2293,7 +2293,7 @@ public AsyncSearchSubmitRequestDescriptor Size(int? size)
return Self;
}

public AsyncSearchSubmitRequestDescriptor Sort(IEnumerable<Elastic.Clients.Elasticsearch.SortCombinations>? sort)
public AsyncSearchSubmitRequestDescriptor Sort(IEnumerable<Elastic.Clients.Elasticsearch.SortOptions>? sort)
{
SortValue = sort;
return Self;
Expand Down Expand Up @@ -2664,7 +2664,7 @@ protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions o
if (SortValue is not null)
{
writer.WritePropertyName("sort");
SingleOrManySerializationHelper.Serialize<Elastic.Clients.Elasticsearch.SortCombinations>(SortValue, writer, options);
SingleOrManySerializationHelper.Serialize<Elastic.Clients.Elasticsearch.SortOptions>(SortValue, writer, options);
}

if (StatsValue is not null)
Expand Down
Loading