diff --git a/Elasticsearch.sln b/Elasticsearch.sln index 92eeb068ebd..06d9e0d6360 100644 --- a/Elasticsearch.sln +++ b/Elasticsearch.sln @@ -37,6 +37,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Directory.Build.props = Directory.Build.props Directory.Build.targets = Directory.Build.targets dotnet-tools.json = dotnet-tools.json + exclusion.dic = exclusion.dic global.json = global.json issue_template.md = issue_template.md LICENSE.txt = LICENSE.txt diff --git a/exclusion.dic b/exclusion.dic index fbef39248b3..b0f6a8c0dbc 100644 --- a/exclusion.dic +++ b/exclusion.dic @@ -3,4 +3,5 @@ json async inferrer elasticsearch -asciidocs \ No newline at end of file +asciidocs +yyyy \ No newline at end of file diff --git a/src/Elastic.Clients.Elasticsearch/Core/Exceptions/ThrowHelper.cs b/src/Elastic.Clients.Elasticsearch/Core/Exceptions/ThrowHelper.cs index 637ea39559c..0f3376692d8 100644 --- a/src/Elastic.Clients.Elasticsearch/Core/Exceptions/ThrowHelper.cs +++ b/src/Elastic.Clients.Elasticsearch/Core/Exceptions/ThrowHelper.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Text.Json; @@ -10,25 +11,31 @@ namespace Elastic.Clients.Elasticsearch; internal static class ThrowHelper { + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] internal static void ThrowJsonException(string? message = null) => throw new JsonException(message); + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] internal static void ThrowUnknownTaggedUnionVariantJsonException(string variantTag, Type interfaceType) => throw new JsonException($"Encountered an unsupported variant tag '{variantTag}' on '{SimplifiedFullName(interfaceType)}', which could not be deserialized."); + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] internal static void ThrowInvalidOperationException(string message) => throw new InvalidOperationException(message); + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] #pragma warning disable IDE0057 // Use range operator private static string SimplifiedFullName(Type type) => type.FullName.Substring(30); #pragma warning restore IDE0057 // Use range operator + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] internal static void ThrowJsonExceptionForMissingSettings() => throw new JsonException("Unable to retrieve client settings for JsonSerializerOptions."); + [DoesNotReturn] [MethodImpl(MethodImplOptions.NoInlining)] internal static void ThrowInvalidOperationForBulkWhenNotIStreamSerializable() => throw new InvalidOperationException("Operation must implement IStreamSerializable."); } diff --git a/src/Elastic.Clients.Elasticsearch/Serialization/TermsAggregateSerializationHelper.cs b/src/Elastic.Clients.Elasticsearch/Serialization/TermsAggregateSerializationHelper.cs index c4d25f17f66..87d1e8e6882 100644 --- a/src/Elastic.Clients.Elasticsearch/Serialization/TermsAggregateSerializationHelper.cs +++ b/src/Elastic.Clients.Elasticsearch/Serialization/TermsAggregateSerializationHelper.cs @@ -15,11 +15,11 @@ internal static class TermsAggregateSerializationHelper private static readonly byte[] s_key = Encoding.UTF8.GetBytes("key"); private static readonly byte s_period = (byte)'.'; - public static bool TryDeserialiseTermsAggregate(string aggregateName, ref Utf8JsonReader reader, JsonSerializerOptions options, out IAggregate? aggregate) + public static bool TryDeserializeTermsAggregate(string aggregateName, ref Utf8JsonReader reader, JsonSerializerOptions options, out IAggregate? aggregate) { aggregate = null; - // We take a copy here so we can read forward to establish the term key type before we resume with final deserialisation. + // We take a copy here so we can read forward to establish the term key type before we resume with final deserialization. var readerCopy = reader; if (JsonHelper.TryReadUntilStringPropertyValue(ref readerCopy, s_buckets)) diff --git a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregateDictionaryConverter.cs b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregateDictionaryConverter.cs index 0f8a3a3008e..60657be4c7f 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregateDictionaryConverter.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregateDictionaryConverter.cs @@ -52,7 +52,7 @@ public static void ReadAggregate(ref Utf8JsonReader reader, JsonSerializerOption case "lterms": case "dterms": { - if (TermsAggregateSerializationHelper.TryDeserialiseTermsAggregate(aggregateName, ref reader, options, out var agg)) + if (TermsAggregateSerializationHelper.TryDeserializeTermsAggregate(aggregateName, ref reader, options, out var agg)) { dictionary.Add(nameParts[1], agg); } diff --git a/src/Elastic.Clients.Elasticsearch/Types/QueryDsl/RangeQuery.cs b/src/Elastic.Clients.Elasticsearch/Types/QueryDsl/RangeQuery.cs new file mode 100644 index 00000000000..81fe9090b62 --- /dev/null +++ b/src/Elastic.Clients.Elasticsearch/Types/QueryDsl/RangeQuery.cs @@ -0,0 +1,238 @@ +// 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.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; +using Elastic.Clients.Elasticsearch.Fluent; + +namespace Elastic.Clients.Elasticsearch.QueryDsl; + +public partial class Query +{ + public bool TryGet([NotNullWhen(true)]out T? query) + { + query = default(T); + + if (Variant is T variant) + { + query = variant; + return true; + } + + return false; + } +} + +[JsonConverter(typeof(RangeQueryConverter))] +public class RangeQuery : SearchQuery +{ + internal RangeQuery() { } +} + +internal sealed class RangeQueryConverter : JsonConverter +{ + public override RangeQuery? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var readerCopy = reader; + + if (readerCopy.TokenType != JsonTokenType.StartObject) + ThrowHelper.ThrowJsonException($"Unexpected JSON detected. Expected {JsonTokenType.StartObject} but read {readerCopy.TokenType}."); + + readerCopy.Read(); // Read past the opening token + readerCopy.Read(); // Read past the field name + + using var jsonDoc = JsonDocument.ParseValue(ref readerCopy); + + if (jsonDoc is null) + return null; + + // When either of these properties are present, we know we have a date range query + if (jsonDoc.RootElement.TryGetProperty("format", out _) || jsonDoc.RootElement.TryGetProperty("time_zone", out _)) + { + return JsonSerializer.Deserialize(ref reader, options); + } + + JsonElement? rangeElement = null; + + if (jsonDoc.RootElement.TryGetProperty("gte", out var gte)) + { + rangeElement = gte; + } + else if (jsonDoc.RootElement.TryGetProperty("gt", out var gt)) + { + rangeElement = gt; + } + else if(jsonDoc.RootElement.TryGetProperty("lte", out var lte)) + { + rangeElement = lte; + } + else if(jsonDoc.RootElement.TryGetProperty("lt", out var lt)) + { + rangeElement = lt; + } + + if (!rangeElement.HasValue) + { + ThrowHelper.ThrowJsonException("Unable to determine type of range query."); + } + + switch (rangeElement.Value.ValueKind) + { + case JsonValueKind.String: + return JsonSerializer.Deserialize(ref reader, options); + case JsonValueKind.Number: + return JsonSerializer.Deserialize(ref reader, options); + } + + ThrowHelper.ThrowJsonException("Unable to deserialize range query."); + + // We never reach here. I wish the flow analysis could infer that this isn't needed with the help of the DoesNotReturn attributes. + return null; + } + + public override void Write(Utf8JsonWriter writer, RangeQuery value, JsonSerializerOptions options) => + JsonSerializer.Serialize(writer, value, value.GetType(), options); +} + + +public sealed class RangeQueryDescriptor : SerializableDescriptor> +{ + private NumberRangeQueryDescriptor _numberRangeQueryDescriptor; + private DateRangeQueryDescriptor _dateRangeQueryDescriptor; + + private Action> _numberRangeQueryDescriptorAction; + private Action> _dateRangeQueryDescriptorAction; + + public RangeQueryDescriptor DateRange(Action> configure) + { + _dateRangeQueryDescriptor = null; + _dateRangeQueryDescriptorAction = configure; + _numberRangeQueryDescriptor = null; + _numberRangeQueryDescriptorAction = null; + + return Self; + } + + public RangeQueryDescriptor NumberRange(Action> configure) + { + _dateRangeQueryDescriptor = null; + _dateRangeQueryDescriptorAction = null; + _numberRangeQueryDescriptor = null; + _numberRangeQueryDescriptorAction = configure; + + return Self; + } + + public RangeQueryDescriptor DateRange(DateRangeQueryDescriptor descriptor) + { + _dateRangeQueryDescriptor = descriptor; + _dateRangeQueryDescriptorAction = null; + _numberRangeQueryDescriptor = null; + _numberRangeQueryDescriptorAction = null; + + return Self; + } + + public RangeQueryDescriptor NumberRange(NumberRangeQueryDescriptor descriptor) + { + _dateRangeQueryDescriptor = null; + _dateRangeQueryDescriptorAction = null; + _numberRangeQueryDescriptor = descriptor; + _numberRangeQueryDescriptorAction = null; + + return Self; + } + + protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings) + { + if (_dateRangeQueryDescriptor is not null) + { + JsonSerializer.Serialize(writer, _dateRangeQueryDescriptor, options); + } + else if (_dateRangeQueryDescriptorAction is not null) + { + JsonSerializer.Serialize(writer, new DateRangeQueryDescriptor(_dateRangeQueryDescriptorAction), options); + } + else if (_numberRangeQueryDescriptor is not null) + { + JsonSerializer.Serialize(writer, _numberRangeQueryDescriptor, options); + } + else if (_numberRangeQueryDescriptorAction is not null) + { + JsonSerializer.Serialize(writer, new NumberRangeQueryDescriptor(_numberRangeQueryDescriptorAction), options); + } + } +} + +public sealed class RangeQueryDescriptor : SerializableDescriptor +{ + private NumberRangeQueryDescriptor _numberRangeQueryDescriptor; + private DateRangeQueryDescriptor _dateRangeQueryDescriptor; + + private Action _numberRangeQueryDescriptorAction; + private Action _dateRangeQueryDescriptorAction; + + public RangeQueryDescriptor DateRange(Action configure) + { + _dateRangeQueryDescriptor = null; + _dateRangeQueryDescriptorAction = configure; + _numberRangeQueryDescriptor = null; + _numberRangeQueryDescriptorAction = null; + + return Self; + } + + public RangeQueryDescriptor NumberRange(Action configure) + { + _dateRangeQueryDescriptor = null; + _dateRangeQueryDescriptorAction = null; + _numberRangeQueryDescriptor = null; + _numberRangeQueryDescriptorAction = configure; + + return Self; + } + + public RangeQueryDescriptor DateRange(DateRangeQueryDescriptor descriptor) + { + _dateRangeQueryDescriptor = descriptor; + _dateRangeQueryDescriptorAction = null; + _numberRangeQueryDescriptor = null; + _numberRangeQueryDescriptorAction = null; + + return Self; + } + + public RangeQueryDescriptor NumberRange(NumberRangeQueryDescriptor descriptor) + { + _dateRangeQueryDescriptor = null; + _dateRangeQueryDescriptorAction = null; + _numberRangeQueryDescriptor = descriptor; + _numberRangeQueryDescriptorAction = null; + + return Self; + } + + protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings) + { + if (_dateRangeQueryDescriptor is not null) + { + JsonSerializer.Serialize(writer, _dateRangeQueryDescriptor, options); + } + else if (_dateRangeQueryDescriptorAction is not null) + { + JsonSerializer.Serialize(writer, new DateRangeQueryDescriptor(_dateRangeQueryDescriptorAction), options); + } + else if (_numberRangeQueryDescriptor is not null) + { + JsonSerializer.Serialize(writer, _numberRangeQueryDescriptor, options); + } + else if (_numberRangeQueryDescriptorAction is not null) + { + JsonSerializer.Serialize(writer, new NumberRangeQueryDescriptor(_numberRangeQueryDescriptorAction), options); + } + } +} + diff --git a/src/Elastic.Clients.Elasticsearch/_Generated/Types/Enums/Enums.QueryDsl.g.cs b/src/Elastic.Clients.Elasticsearch/_Generated/Types/Enums/Enums.QueryDsl.g.cs index 894a0f67b3b..14341b2445a 100644 --- a/src/Elastic.Clients.Elasticsearch/_Generated/Types/Enums/Enums.QueryDsl.g.cs +++ b/src/Elastic.Clients.Elasticsearch/_Generated/Types/Enums/Enums.QueryDsl.g.cs @@ -453,6 +453,55 @@ public override void Write(Utf8JsonWriter writer, Operator value, JsonSerializer } } +[JsonConverter(typeof(RangeRelationConverter))] +public enum RangeRelation +{ + [EnumMember(Value = "within")] + Within, + [EnumMember(Value = "intersects")] + Intersects, + [EnumMember(Value = "contains")] + Contains +} + +internal sealed class RangeRelationConverter : JsonConverter +{ + public override RangeRelation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var enumString = reader.GetString(); + switch (enumString) + { + case "within": + return RangeRelation.Within; + case "intersects": + return RangeRelation.Intersects; + case "contains": + return RangeRelation.Contains; + } + + ThrowHelper.ThrowJsonException(); + return default; + } + + public override void Write(Utf8JsonWriter writer, RangeRelation value, JsonSerializerOptions options) + { + switch (value) + { + case RangeRelation.Within: + writer.WriteStringValue("within"); + return; + case RangeRelation.Intersects: + writer.WriteStringValue("intersects"); + return; + case RangeRelation.Contains: + writer.WriteStringValue("contains"); + return; + } + + writer.WriteNullValue(); + } +} + [JsonConverter(typeof(TextQueryTypeConverter))] public enum TextQueryType { diff --git a/src/Elastic.Clients.Elasticsearch/_Generated/Types/QueryDsl/DateRangeQuery.g.cs b/src/Elastic.Clients.Elasticsearch/_Generated/Types/QueryDsl/DateRangeQuery.g.cs new file mode 100644 index 00000000000..127afa60504 --- /dev/null +++ b/src/Elastic.Clients.Elasticsearch/_Generated/Types/QueryDsl/DateRangeQuery.g.cs @@ -0,0 +1,635 @@ +// 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. +// +// ███╗ ██╗ ██████╗ ████████╗██╗ ██████╗███████╗ +// ████╗ ██║██╔═══██╗╚══██╔══╝██║██╔════╝██╔════╝ +// ██╔██╗ ██║██║ ██║ ██║ ██║██║ █████╗ +// ██║╚██╗██║██║ ██║ ██║ ██║██║ ██╔══╝ +// ██║ ╚████║╚██████╔╝ ██║ ██║╚██████╗███████╗ +// ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝ +// ------------------------------------------------ +// +// This file is automatically generated. +// Please do not edit these files manually. +// +// ------------------------------------------------ + +using Elastic.Clients.Elasticsearch.Fluent; +using Elastic.Clients.Elasticsearch.Serialization; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Text.Json; +using System.Text.Json.Serialization; + +#nullable restore +namespace Elastic.Clients.Elasticsearch.QueryDsl; +internal sealed partial class DateRangeQueryConverter : JsonConverter +{ + public override DateRangeQuery Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.StartObject) + throw new JsonException("Unexpected JSON detected."); + reader.Read(); + var fieldName = reader.GetString(); + reader.Read(); + var variant = new DateRangeQuery(fieldName); + while (reader.Read() && reader.TokenType != JsonTokenType.EndObject) + { + if (reader.TokenType == JsonTokenType.PropertyName) + { + var property = reader.GetString(); + if (property == "_name") + { + variant.QueryName = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "boost") + { + variant.Boost = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "format") + { + variant.Format = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "from") + { + variant.From = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "gt") + { + variant.Gt = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "gte") + { + variant.Gte = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "lt") + { + variant.Lt = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "lte") + { + variant.Lte = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "relation") + { + variant.Relation = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "time_zone") + { + variant.TimeZone = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "to") + { + variant.To = JsonSerializer.Deserialize(ref reader, options); + continue; + } + } + } + + reader.Read(); + return variant; + } + + public override void Write(Utf8JsonWriter writer, DateRangeQuery value, JsonSerializerOptions options) + { + if (value.Field is null) + throw new JsonException("Unable to serialize DateRangeQuery because the `Field` property is not set. Field name queries must include a valid field name."); + if (options.TryGetClientSettings(out var settings)) + { + writer.WriteStartObject(); + writer.WritePropertyName(settings.Inferrer.Field(value.Field)); + writer.WriteStartObject(); + if (!string.IsNullOrEmpty(value.QueryName)) + { + writer.WritePropertyName("_name"); + writer.WriteStringValue(value.QueryName); + } + + if (value.Boost.HasValue) + { + writer.WritePropertyName("boost"); + writer.WriteNumberValue(value.Boost.Value); + } + + if (value.Format is not null) + { + writer.WritePropertyName("format"); + JsonSerializer.Serialize(writer, value.Format, options); + } + + if (value.From is not null) + { + writer.WritePropertyName("from"); + JsonSerializer.Serialize(writer, value.From, options); + } + + if (value.Gt is not null) + { + writer.WritePropertyName("gt"); + JsonSerializer.Serialize(writer, value.Gt, options); + } + + if (value.Gte is not null) + { + writer.WritePropertyName("gte"); + JsonSerializer.Serialize(writer, value.Gte, options); + } + + if (value.Lt is not null) + { + writer.WritePropertyName("lt"); + JsonSerializer.Serialize(writer, value.Lt, options); + } + + if (value.Lte is not null) + { + writer.WritePropertyName("lte"); + JsonSerializer.Serialize(writer, value.Lte, options); + } + + if (value.Relation is not null) + { + writer.WritePropertyName("relation"); + JsonSerializer.Serialize(writer, value.Relation, options); + } + + if (value.TimeZone is not null) + { + writer.WritePropertyName("time_zone"); + JsonSerializer.Serialize(writer, value.TimeZone, options); + } + + if (value.To is not null) + { + writer.WritePropertyName("to"); + JsonSerializer.Serialize(writer, value.To, options); + } + + writer.WriteEndObject(); + writer.WriteEndObject(); + return; + } + + throw new JsonException("Unable to retrieve client settings required to infer field."); + } +} + +[JsonConverter(typeof(DateRangeQueryConverter))] +public sealed partial class DateRangeQuery : RangeQuery +{ + public DateRangeQuery(Field field) + { + if (field is null) + throw new ArgumentNullException(nameof(field)); + Field = field; + } + + public string? QueryName { get; set; } + + public float? Boost { get; set; } + + public string? Format { get; set; } + + public Elastic.Clients.Elasticsearch.DateMath? From { get; set; } + + public Elastic.Clients.Elasticsearch.DateMath? Gt { get; set; } + + public Elastic.Clients.Elasticsearch.DateMath? Gte { get; set; } + + public Elastic.Clients.Elasticsearch.DateMath? Lt { get; set; } + + public Elastic.Clients.Elasticsearch.DateMath? Lte { get; set; } + + public Elastic.Clients.Elasticsearch.QueryDsl.RangeRelation? Relation { get; set; } + + public string? TimeZone { get; set; } + + public Elastic.Clients.Elasticsearch.DateMath? To { get; set; } + + public Elastic.Clients.Elasticsearch.Field Field { get; set; } + + public static implicit operator Query(DateRangeQuery dateRangeQuery) => QueryDsl.Query.Range(dateRangeQuery); +} + +public sealed partial class DateRangeQueryDescriptor : SerializableDescriptor> +{ + internal DateRangeQueryDescriptor(Action> configure) => configure.Invoke(this); + internal DateRangeQueryDescriptor() : base() + { + } + + public DateRangeQueryDescriptor(Field field) + { + if (field is null) + throw new ArgumentNullException(nameof(field)); + FieldValue = field; + } + + public DateRangeQueryDescriptor(Expression> field) + { + if (field is null) + throw new ArgumentNullException(nameof(field)); + FieldValue = field; + } + + private string? QueryNameValue { get; set; } + + private float? BoostValue { get; set; } + + private Elastic.Clients.Elasticsearch.Field FieldValue { get; set; } + + private string? FormatValue { get; set; } + + private Elastic.Clients.Elasticsearch.DateMath? FromValue { get; set; } + + private Elastic.Clients.Elasticsearch.DateMath? GtValue { get; set; } + + private Elastic.Clients.Elasticsearch.DateMath? GteValue { get; set; } + + private Elastic.Clients.Elasticsearch.DateMath? LtValue { get; set; } + + private Elastic.Clients.Elasticsearch.DateMath? LteValue { get; set; } + + private Elastic.Clients.Elasticsearch.QueryDsl.RangeRelation? RelationValue { get; set; } + + private string? TimeZoneValue { get; set; } + + private Elastic.Clients.Elasticsearch.DateMath? ToValue { get; set; } + + public DateRangeQueryDescriptor QueryName(string? queryName) + { + QueryNameValue = queryName; + return Self; + } + + public DateRangeQueryDescriptor Boost(float? boost) + { + BoostValue = boost; + return Self; + } + + public DateRangeQueryDescriptor Field(Elastic.Clients.Elasticsearch.Field field) + { + FieldValue = field; + return Self; + } + + public DateRangeQueryDescriptor Field(Expression> field) + { + FieldValue = field; + return Self; + } + + public DateRangeQueryDescriptor Format(string? format) + { + FormatValue = format; + return Self; + } + + public DateRangeQueryDescriptor From(Elastic.Clients.Elasticsearch.DateMath? from) + { + FromValue = from; + return Self; + } + + public DateRangeQueryDescriptor Gt(Elastic.Clients.Elasticsearch.DateMath? gt) + { + GtValue = gt; + return Self; + } + + public DateRangeQueryDescriptor Gte(Elastic.Clients.Elasticsearch.DateMath? gte) + { + GteValue = gte; + return Self; + } + + public DateRangeQueryDescriptor Lt(Elastic.Clients.Elasticsearch.DateMath? lt) + { + LtValue = lt; + return Self; + } + + public DateRangeQueryDescriptor Lte(Elastic.Clients.Elasticsearch.DateMath? lte) + { + LteValue = lte; + return Self; + } + + public DateRangeQueryDescriptor Relation(Elastic.Clients.Elasticsearch.QueryDsl.RangeRelation? relation) + { + RelationValue = relation; + return Self; + } + + public DateRangeQueryDescriptor TimeZone(string? timeZone) + { + TimeZoneValue = timeZone; + return Self; + } + + public DateRangeQueryDescriptor To(Elastic.Clients.Elasticsearch.DateMath? to) + { + ToValue = to; + return Self; + } + + protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings) + { + if (FieldValue is null) + throw new JsonException("Unable to serialize field name query descriptor with a null field. Ensure you use a suitable descriptor constructor or call the Field method, passing a non-null value for the field argument."); + writer.WriteStartObject(); + writer.WritePropertyName(settings.Inferrer.Field(FieldValue)); + writer.WriteStartObject(); + if (!string.IsNullOrEmpty(QueryNameValue)) + { + writer.WritePropertyName("_name"); + writer.WriteStringValue(QueryNameValue); + } + + if (BoostValue.HasValue) + { + writer.WritePropertyName("boost"); + writer.WriteNumberValue(BoostValue.Value); + } + + if (FormatValue is not null) + { + writer.WritePropertyName("format"); + JsonSerializer.Serialize(writer, FormatValue, options); + } + + if (FromValue is not null) + { + writer.WritePropertyName("from"); + JsonSerializer.Serialize(writer, FromValue, options); + } + + if (GtValue is not null) + { + writer.WritePropertyName("gt"); + JsonSerializer.Serialize(writer, GtValue, options); + } + + if (GteValue is not null) + { + writer.WritePropertyName("gte"); + JsonSerializer.Serialize(writer, GteValue, options); + } + + if (LtValue is not null) + { + writer.WritePropertyName("lt"); + JsonSerializer.Serialize(writer, LtValue, options); + } + + if (LteValue is not null) + { + writer.WritePropertyName("lte"); + JsonSerializer.Serialize(writer, LteValue, options); + } + + if (RelationValue is not null) + { + writer.WritePropertyName("relation"); + JsonSerializer.Serialize(writer, RelationValue, options); + } + + if (TimeZoneValue is not null) + { + writer.WritePropertyName("time_zone"); + JsonSerializer.Serialize(writer, TimeZoneValue, options); + } + + if (ToValue is not null) + { + writer.WritePropertyName("to"); + JsonSerializer.Serialize(writer, ToValue, options); + } + + writer.WriteEndObject(); + writer.WriteEndObject(); + } +} + +public sealed partial class DateRangeQueryDescriptor : SerializableDescriptor +{ + internal DateRangeQueryDescriptor(Action configure) => configure.Invoke(this); + internal DateRangeQueryDescriptor() : base() + { + } + + public DateRangeQueryDescriptor(Field field) + { + if (field is null) + throw new ArgumentNullException(nameof(field)); + FieldValue = field; + } + + private string? QueryNameValue { get; set; } + + private float? BoostValue { get; set; } + + private Elastic.Clients.Elasticsearch.Field FieldValue { get; set; } + + private string? FormatValue { get; set; } + + private Elastic.Clients.Elasticsearch.DateMath? FromValue { get; set; } + + private Elastic.Clients.Elasticsearch.DateMath? GtValue { get; set; } + + private Elastic.Clients.Elasticsearch.DateMath? GteValue { get; set; } + + private Elastic.Clients.Elasticsearch.DateMath? LtValue { get; set; } + + private Elastic.Clients.Elasticsearch.DateMath? LteValue { get; set; } + + private Elastic.Clients.Elasticsearch.QueryDsl.RangeRelation? RelationValue { get; set; } + + private string? TimeZoneValue { get; set; } + + private Elastic.Clients.Elasticsearch.DateMath? ToValue { get; set; } + + public DateRangeQueryDescriptor QueryName(string? queryName) + { + QueryNameValue = queryName; + return Self; + } + + public DateRangeQueryDescriptor Boost(float? boost) + { + BoostValue = boost; + return Self; + } + + public DateRangeQueryDescriptor Field(Elastic.Clients.Elasticsearch.Field field) + { + FieldValue = field; + return Self; + } + + public DateRangeQueryDescriptor Field(Expression> field) + { + FieldValue = field; + return Self; + } + + public DateRangeQueryDescriptor Field(Expression> field) + { + FieldValue = field; + return Self; + } + + public DateRangeQueryDescriptor Format(string? format) + { + FormatValue = format; + return Self; + } + + public DateRangeQueryDescriptor From(Elastic.Clients.Elasticsearch.DateMath? from) + { + FromValue = from; + return Self; + } + + public DateRangeQueryDescriptor Gt(Elastic.Clients.Elasticsearch.DateMath? gt) + { + GtValue = gt; + return Self; + } + + public DateRangeQueryDescriptor Gte(Elastic.Clients.Elasticsearch.DateMath? gte) + { + GteValue = gte; + return Self; + } + + public DateRangeQueryDescriptor Lt(Elastic.Clients.Elasticsearch.DateMath? lt) + { + LtValue = lt; + return Self; + } + + public DateRangeQueryDescriptor Lte(Elastic.Clients.Elasticsearch.DateMath? lte) + { + LteValue = lte; + return Self; + } + + public DateRangeQueryDescriptor Relation(Elastic.Clients.Elasticsearch.QueryDsl.RangeRelation? relation) + { + RelationValue = relation; + return Self; + } + + public DateRangeQueryDescriptor TimeZone(string? timeZone) + { + TimeZoneValue = timeZone; + return Self; + } + + public DateRangeQueryDescriptor To(Elastic.Clients.Elasticsearch.DateMath? to) + { + ToValue = to; + return Self; + } + + protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings) + { + if (FieldValue is null) + throw new JsonException("Unable to serialize field name query descriptor with a null field. Ensure you use a suitable descriptor constructor or call the Field method, passing a non-null value for the field argument."); + writer.WriteStartObject(); + writer.WritePropertyName(settings.Inferrer.Field(FieldValue)); + writer.WriteStartObject(); + if (!string.IsNullOrEmpty(QueryNameValue)) + { + writer.WritePropertyName("_name"); + writer.WriteStringValue(QueryNameValue); + } + + if (BoostValue.HasValue) + { + writer.WritePropertyName("boost"); + writer.WriteNumberValue(BoostValue.Value); + } + + if (FormatValue is not null) + { + writer.WritePropertyName("format"); + JsonSerializer.Serialize(writer, FormatValue, options); + } + + if (FromValue is not null) + { + writer.WritePropertyName("from"); + JsonSerializer.Serialize(writer, FromValue, options); + } + + if (GtValue is not null) + { + writer.WritePropertyName("gt"); + JsonSerializer.Serialize(writer, GtValue, options); + } + + if (GteValue is not null) + { + writer.WritePropertyName("gte"); + JsonSerializer.Serialize(writer, GteValue, options); + } + + if (LtValue is not null) + { + writer.WritePropertyName("lt"); + JsonSerializer.Serialize(writer, LtValue, options); + } + + if (LteValue is not null) + { + writer.WritePropertyName("lte"); + JsonSerializer.Serialize(writer, LteValue, options); + } + + if (RelationValue is not null) + { + writer.WritePropertyName("relation"); + JsonSerializer.Serialize(writer, RelationValue, options); + } + + if (TimeZoneValue is not null) + { + writer.WritePropertyName("time_zone"); + JsonSerializer.Serialize(writer, TimeZoneValue, options); + } + + if (ToValue is not null) + { + writer.WritePropertyName("to"); + JsonSerializer.Serialize(writer, ToValue, options); + } + + writer.WriteEndObject(); + writer.WriteEndObject(); + } +} \ No newline at end of file diff --git a/src/Elastic.Clients.Elasticsearch/_Generated/Types/QueryDsl/NumberRangeQuery.g.cs b/src/Elastic.Clients.Elasticsearch/_Generated/Types/QueryDsl/NumberRangeQuery.g.cs new file mode 100644 index 00000000000..251e039e9ab --- /dev/null +++ b/src/Elastic.Clients.Elasticsearch/_Generated/Types/QueryDsl/NumberRangeQuery.g.cs @@ -0,0 +1,551 @@ +// 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. +// +// ███╗ ██╗ ██████╗ ████████╗██╗ ██████╗███████╗ +// ████╗ ██║██╔═══██╗╚══██╔══╝██║██╔════╝██╔════╝ +// ██╔██╗ ██║██║ ██║ ██║ ██║██║ █████╗ +// ██║╚██╗██║██║ ██║ ██║ ██║██║ ██╔══╝ +// ██║ ╚████║╚██████╔╝ ██║ ██║╚██████╗███████╗ +// ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝╚══════╝ +// ------------------------------------------------ +// +// This file is automatically generated. +// Please do not edit these files manually. +// +// ------------------------------------------------ + +using Elastic.Clients.Elasticsearch.Fluent; +using Elastic.Clients.Elasticsearch.Serialization; +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Text.Json; +using System.Text.Json.Serialization; + +#nullable restore +namespace Elastic.Clients.Elasticsearch.QueryDsl; +internal sealed partial class NumberRangeQueryConverter : JsonConverter +{ + public override NumberRangeQuery Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.StartObject) + throw new JsonException("Unexpected JSON detected."); + reader.Read(); + var fieldName = reader.GetString(); + reader.Read(); + var variant = new NumberRangeQuery(fieldName); + while (reader.Read() && reader.TokenType != JsonTokenType.EndObject) + { + if (reader.TokenType == JsonTokenType.PropertyName) + { + var property = reader.GetString(); + if (property == "_name") + { + variant.QueryName = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "boost") + { + variant.Boost = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "from") + { + variant.From = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "gt") + { + variant.Gt = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "gte") + { + variant.Gte = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "lt") + { + variant.Lt = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "lte") + { + variant.Lte = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "relation") + { + variant.Relation = JsonSerializer.Deserialize(ref reader, options); + continue; + } + + if (property == "to") + { + variant.To = JsonSerializer.Deserialize(ref reader, options); + continue; + } + } + } + + reader.Read(); + return variant; + } + + public override void Write(Utf8JsonWriter writer, NumberRangeQuery value, JsonSerializerOptions options) + { + if (value.Field is null) + throw new JsonException("Unable to serialize NumberRangeQuery because the `Field` property is not set. Field name queries must include a valid field name."); + if (options.TryGetClientSettings(out var settings)) + { + writer.WriteStartObject(); + writer.WritePropertyName(settings.Inferrer.Field(value.Field)); + writer.WriteStartObject(); + if (!string.IsNullOrEmpty(value.QueryName)) + { + writer.WritePropertyName("_name"); + writer.WriteStringValue(value.QueryName); + } + + if (value.Boost.HasValue) + { + writer.WritePropertyName("boost"); + writer.WriteNumberValue(value.Boost.Value); + } + + if (value.From.HasValue) + { + writer.WritePropertyName("from"); + writer.WriteNumberValue(value.From.Value); + } + + if (value.Gt.HasValue) + { + writer.WritePropertyName("gt"); + writer.WriteNumberValue(value.Gt.Value); + } + + if (value.Gte.HasValue) + { + writer.WritePropertyName("gte"); + writer.WriteNumberValue(value.Gte.Value); + } + + if (value.Lt.HasValue) + { + writer.WritePropertyName("lt"); + writer.WriteNumberValue(value.Lt.Value); + } + + if (value.Lte.HasValue) + { + writer.WritePropertyName("lte"); + writer.WriteNumberValue(value.Lte.Value); + } + + if (value.Relation is not null) + { + writer.WritePropertyName("relation"); + JsonSerializer.Serialize(writer, value.Relation, options); + } + + if (value.To.HasValue) + { + writer.WritePropertyName("to"); + writer.WriteNumberValue(value.To.Value); + } + + writer.WriteEndObject(); + writer.WriteEndObject(); + return; + } + + throw new JsonException("Unable to retrieve client settings required to infer field."); + } +} + +[JsonConverter(typeof(NumberRangeQueryConverter))] +public sealed partial class NumberRangeQuery : RangeQuery +{ + public NumberRangeQuery(Field field) + { + if (field is null) + throw new ArgumentNullException(nameof(field)); + Field = field; + } + + public string? QueryName { get; set; } + + public float? Boost { get; set; } + + public double? From { get; set; } + + public double? Gt { get; set; } + + public double? Gte { get; set; } + + public double? Lt { get; set; } + + public double? Lte { get; set; } + + public Elastic.Clients.Elasticsearch.QueryDsl.RangeRelation? Relation { get; set; } + + public double? To { get; set; } + + public Elastic.Clients.Elasticsearch.Field Field { get; set; } + + public static implicit operator Query(NumberRangeQuery numberRangeQuery) => QueryDsl.Query.Range(numberRangeQuery); +} + +public sealed partial class NumberRangeQueryDescriptor : SerializableDescriptor> +{ + internal NumberRangeQueryDescriptor(Action> configure) => configure.Invoke(this); + internal NumberRangeQueryDescriptor() : base() + { + } + + public NumberRangeQueryDescriptor(Field field) + { + if (field is null) + throw new ArgumentNullException(nameof(field)); + FieldValue = field; + } + + public NumberRangeQueryDescriptor(Expression> field) + { + if (field is null) + throw new ArgumentNullException(nameof(field)); + FieldValue = field; + } + + private string? QueryNameValue { get; set; } + + private float? BoostValue { get; set; } + + private Elastic.Clients.Elasticsearch.Field FieldValue { get; set; } + + private double? FromValue { get; set; } + + private double? GtValue { get; set; } + + private double? GteValue { get; set; } + + private double? LtValue { get; set; } + + private double? LteValue { get; set; } + + private Elastic.Clients.Elasticsearch.QueryDsl.RangeRelation? RelationValue { get; set; } + + private double? ToValue { get; set; } + + public NumberRangeQueryDescriptor QueryName(string? queryName) + { + QueryNameValue = queryName; + return Self; + } + + public NumberRangeQueryDescriptor Boost(float? boost) + { + BoostValue = boost; + return Self; + } + + public NumberRangeQueryDescriptor Field(Elastic.Clients.Elasticsearch.Field field) + { + FieldValue = field; + return Self; + } + + public NumberRangeQueryDescriptor Field(Expression> field) + { + FieldValue = field; + return Self; + } + + public NumberRangeQueryDescriptor From(double? from) + { + FromValue = from; + return Self; + } + + public NumberRangeQueryDescriptor Gt(double? gt) + { + GtValue = gt; + return Self; + } + + public NumberRangeQueryDescriptor Gte(double? gte) + { + GteValue = gte; + return Self; + } + + public NumberRangeQueryDescriptor Lt(double? lt) + { + LtValue = lt; + return Self; + } + + public NumberRangeQueryDescriptor Lte(double? lte) + { + LteValue = lte; + return Self; + } + + public NumberRangeQueryDescriptor Relation(Elastic.Clients.Elasticsearch.QueryDsl.RangeRelation? relation) + { + RelationValue = relation; + return Self; + } + + public NumberRangeQueryDescriptor To(double? to) + { + ToValue = to; + return Self; + } + + protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings) + { + if (FieldValue is null) + throw new JsonException("Unable to serialize field name query descriptor with a null field. Ensure you use a suitable descriptor constructor or call the Field method, passing a non-null value for the field argument."); + writer.WriteStartObject(); + writer.WritePropertyName(settings.Inferrer.Field(FieldValue)); + writer.WriteStartObject(); + if (!string.IsNullOrEmpty(QueryNameValue)) + { + writer.WritePropertyName("_name"); + writer.WriteStringValue(QueryNameValue); + } + + if (BoostValue.HasValue) + { + writer.WritePropertyName("boost"); + writer.WriteNumberValue(BoostValue.Value); + } + + if (FromValue.HasValue) + { + writer.WritePropertyName("from"); + writer.WriteNumberValue(FromValue.Value); + } + + if (GtValue.HasValue) + { + writer.WritePropertyName("gt"); + writer.WriteNumberValue(GtValue.Value); + } + + if (GteValue.HasValue) + { + writer.WritePropertyName("gte"); + writer.WriteNumberValue(GteValue.Value); + } + + if (LtValue.HasValue) + { + writer.WritePropertyName("lt"); + writer.WriteNumberValue(LtValue.Value); + } + + if (LteValue.HasValue) + { + writer.WritePropertyName("lte"); + writer.WriteNumberValue(LteValue.Value); + } + + if (RelationValue is not null) + { + writer.WritePropertyName("relation"); + JsonSerializer.Serialize(writer, RelationValue, options); + } + + if (ToValue.HasValue) + { + writer.WritePropertyName("to"); + writer.WriteNumberValue(ToValue.Value); + } + + writer.WriteEndObject(); + writer.WriteEndObject(); + } +} + +public sealed partial class NumberRangeQueryDescriptor : SerializableDescriptor +{ + internal NumberRangeQueryDescriptor(Action configure) => configure.Invoke(this); + internal NumberRangeQueryDescriptor() : base() + { + } + + public NumberRangeQueryDescriptor(Field field) + { + if (field is null) + throw new ArgumentNullException(nameof(field)); + FieldValue = field; + } + + private string? QueryNameValue { get; set; } + + private float? BoostValue { get; set; } + + private Elastic.Clients.Elasticsearch.Field FieldValue { get; set; } + + private double? FromValue { get; set; } + + private double? GtValue { get; set; } + + private double? GteValue { get; set; } + + private double? LtValue { get; set; } + + private double? LteValue { get; set; } + + private Elastic.Clients.Elasticsearch.QueryDsl.RangeRelation? RelationValue { get; set; } + + private double? ToValue { get; set; } + + public NumberRangeQueryDescriptor QueryName(string? queryName) + { + QueryNameValue = queryName; + return Self; + } + + public NumberRangeQueryDescriptor Boost(float? boost) + { + BoostValue = boost; + return Self; + } + + public NumberRangeQueryDescriptor Field(Elastic.Clients.Elasticsearch.Field field) + { + FieldValue = field; + return Self; + } + + public NumberRangeQueryDescriptor Field(Expression> field) + { + FieldValue = field; + return Self; + } + + public NumberRangeQueryDescriptor Field(Expression> field) + { + FieldValue = field; + return Self; + } + + public NumberRangeQueryDescriptor From(double? from) + { + FromValue = from; + return Self; + } + + public NumberRangeQueryDescriptor Gt(double? gt) + { + GtValue = gt; + return Self; + } + + public NumberRangeQueryDescriptor Gte(double? gte) + { + GteValue = gte; + return Self; + } + + public NumberRangeQueryDescriptor Lt(double? lt) + { + LtValue = lt; + return Self; + } + + public NumberRangeQueryDescriptor Lte(double? lte) + { + LteValue = lte; + return Self; + } + + public NumberRangeQueryDescriptor Relation(Elastic.Clients.Elasticsearch.QueryDsl.RangeRelation? relation) + { + RelationValue = relation; + return Self; + } + + public NumberRangeQueryDescriptor To(double? to) + { + ToValue = to; + return Self; + } + + protected override void Serialize(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings) + { + if (FieldValue is null) + throw new JsonException("Unable to serialize field name query descriptor with a null field. Ensure you use a suitable descriptor constructor or call the Field method, passing a non-null value for the field argument."); + writer.WriteStartObject(); + writer.WritePropertyName(settings.Inferrer.Field(FieldValue)); + writer.WriteStartObject(); + if (!string.IsNullOrEmpty(QueryNameValue)) + { + writer.WritePropertyName("_name"); + writer.WriteStringValue(QueryNameValue); + } + + if (BoostValue.HasValue) + { + writer.WritePropertyName("boost"); + writer.WriteNumberValue(BoostValue.Value); + } + + if (FromValue.HasValue) + { + writer.WritePropertyName("from"); + writer.WriteNumberValue(FromValue.Value); + } + + if (GtValue.HasValue) + { + writer.WritePropertyName("gt"); + writer.WriteNumberValue(GtValue.Value); + } + + if (GteValue.HasValue) + { + writer.WritePropertyName("gte"); + writer.WriteNumberValue(GteValue.Value); + } + + if (LtValue.HasValue) + { + writer.WritePropertyName("lt"); + writer.WriteNumberValue(LtValue.Value); + } + + if (LteValue.HasValue) + { + writer.WritePropertyName("lte"); + writer.WriteNumberValue(LteValue.Value); + } + + if (RelationValue is not null) + { + writer.WritePropertyName("relation"); + JsonSerializer.Serialize(writer, RelationValue, options); + } + + if (ToValue.HasValue) + { + writer.WritePropertyName("to"); + writer.WriteNumberValue(ToValue.Value); + } + + writer.WriteEndObject(); + writer.WriteEndObject(); + } +} \ No newline at end of file diff --git a/src/Elastic.Clients.Elasticsearch/_Generated/Types/QueryDsl/Query.g.cs b/src/Elastic.Clients.Elasticsearch/_Generated/Types/QueryDsl/Query.g.cs index 10c8a64ff20..2b56504afbf 100644 --- a/src/Elastic.Clients.Elasticsearch/_Generated/Types/QueryDsl/Query.g.cs +++ b/src/Elastic.Clients.Elasticsearch/_Generated/Types/QueryDsl/Query.g.cs @@ -70,6 +70,7 @@ internal Query(string variantName, object variant) public static Query Percolate(Elastic.Clients.Elasticsearch.QueryDsl.PercolateQuery percolateQuery) => new Query("percolate", percolateQuery); public static Query Prefix(Elastic.Clients.Elasticsearch.QueryDsl.PrefixQuery prefixQuery) => new Query("prefix", prefixQuery); public static Query QueryString(Elastic.Clients.Elasticsearch.QueryDsl.QueryStringQuery queryStringQuery) => new Query("query_string", queryStringQuery); + public static Query Range(Elastic.Clients.Elasticsearch.QueryDsl.RangeQuery rangeQuery) => new Query("range", rangeQuery); public static Query RankFeature(Elastic.Clients.Elasticsearch.QueryDsl.RankFeatureQuery rankFeatureQuery) => new Query("rank_feature", rankFeatureQuery); public static Query Regexp(Elastic.Clients.Elasticsearch.QueryDsl.RegexpQuery regexpQuery) => new Query("regexp", regexpQuery); public static Query Script(Elastic.Clients.Elasticsearch.QueryDsl.ScriptQuery scriptQuery) => new Query("script", scriptQuery); @@ -289,6 +290,13 @@ public override Query Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSe return new Query(propertyName, variant); } + if (propertyName == "range") + { + var variant = JsonSerializer.Deserialize(ref reader, options); + reader.Read(); + return new Query(propertyName, variant); + } + if (propertyName == "rank_feature") { var variant = JsonSerializer.Deserialize(ref reader, options); @@ -502,6 +510,9 @@ public override void Write(Utf8JsonWriter writer, Query value, JsonSerializerOpt case "query_string": JsonSerializer.Serialize(writer, (Elastic.Clients.Elasticsearch.QueryDsl.QueryStringQuery)value.Variant, options); break; + case "range": + JsonSerializer.Serialize(writer, (Elastic.Clients.Elasticsearch.QueryDsl.RangeQuery)value.Variant, options); + break; case "rank_feature": JsonSerializer.Serialize(writer, (Elastic.Clients.Elasticsearch.QueryDsl.RankFeatureQuery)value.Variant, options); break; @@ -648,6 +659,8 @@ private QueryDescriptor Set(object variant, string variantName) public QueryDescriptor Prefix(Action> configure) => Set(configure, "prefix"); public QueryDescriptor QueryString(QueryStringQuery queryStringQuery) => Set(queryStringQuery, "query_string"); public QueryDescriptor QueryString(Action> configure) => Set(configure, "query_string"); + public QueryDescriptor Range(RangeQuery rangeQuery) => Set(rangeQuery, "range"); + public QueryDescriptor Range(Action> configure) => Set(configure, "range"); public QueryDescriptor RankFeature(RankFeatureQuery rankFeatureQuery) => Set(rankFeatureQuery, "rank_feature"); public QueryDescriptor RankFeature(Action> configure) => Set(configure, "rank_feature"); public QueryDescriptor Regexp(RegexpQuery regexpQuery) => Set(regexpQuery, "regexp"); @@ -814,6 +827,9 @@ private QueryDescriptor Set(object variant, string variantName) public QueryDescriptor QueryString(QueryStringQuery queryStringQuery) => Set(queryStringQuery, "query_string"); public QueryDescriptor QueryString(Action configure) => Set(configure, "query_string"); public QueryDescriptor QueryString(Action> configure) => Set(configure, "query_string"); + public QueryDescriptor Range(RangeQuery rangeQuery) => Set(rangeQuery, "range"); + public QueryDescriptor Range(Action configure) => Set(configure, "range"); + public QueryDescriptor Range(Action> configure) => Set(configure, "range"); public QueryDescriptor RankFeature(RankFeatureQuery rankFeatureQuery) => Set(rankFeatureQuery, "rank_feature"); public QueryDescriptor RankFeature(Action configure) => Set(configure, "rank_feature"); public QueryDescriptor RankFeature(Action> configure) => Set(configure, "rank_feature"); diff --git a/tests/Tests/Serialization/Queries/RangeQuerySerializationTests.cs b/tests/Tests/Serialization/Queries/RangeQuerySerializationTests.cs new file mode 100644 index 00000000000..6b53f12af0f --- /dev/null +++ b/tests/Tests/Serialization/Queries/RangeQuerySerializationTests.cs @@ -0,0 +1,182 @@ +// 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.Threading.Tasks; +using Elastic.Clients.Elasticsearch.QueryDsl; +using Tests.Domain; +using VerifyXunit; + +namespace Tests.Serialization.Queries; + +[UsesVerify] +public class RangeQuerySerializationTests : SerializerTestBase +{ + private const string Field = "my-field"; + private const string QueryName = "named_query"; + + private static readonly DateRangeQuery DateRangeQueryWithoutFormat = new(Field) + { + QueryName = QueryName, + Boost = 1.1f, + Gte = DateMath.Now.Subtract("1y").RoundTo(DateMathTimeUnit.Month), + Lt = DateMath.Now + }; + + private static readonly NumberRangeQuery NumberRangeQuery = new(Field) + { + QueryName = QueryName, + Boost = 1.1f, + Gte = 100, + Lt = 1000 + }; + + private static void VerifyQuery(DateRangeQuery dateRangeQuery) + { + dateRangeQuery.Should().NotBeNull(); + dateRangeQuery.QueryName.Should().Be(QueryName); + dateRangeQuery.Field.Should().Be(Field); + dateRangeQuery.Boost.Should().Be(1.1f); + dateRangeQuery.Gte.ToString().Should().Be("now-1y/M"); + dateRangeQuery.Lt.ToString().Should().Be("now"); + } + + private static void VerifyQuery(NumberRangeQuery dateRangeQuery) + { + dateRangeQuery.Should().NotBeNull(); + dateRangeQuery.QueryName.Should().Be(QueryName); + dateRangeQuery.Field.Should().Be(Field); + dateRangeQuery.Boost.Should().Be(1.1f); + dateRangeQuery.Gte.Should().Be(100); + dateRangeQuery.Lt.Should().Be(1000); + } + + [U] + public async Task DateRangeQuery_SerializesCorrectly() + { + var query = DateRangeQueryWithoutFormat; + + var json = await SerializeAndVerifyJsonAsync(query); + + var dateRangeQuery = DeserializeJsonString(json); + + VerifyQuery(dateRangeQuery); + + var rangeQuery = DeserializeJsonString(json); + + dateRangeQuery = rangeQuery as DateRangeQuery; + + VerifyQuery(dateRangeQuery); + } + + [U] + public async Task DateRangeQuery_WithFormat_SerializesCorrectly() + { + const string dateFormat = @"dd/MM/yyyy||yyyy"; + + var query = DateRangeQueryWithoutFormat; + query.Format = dateFormat; + + var json = await SerializeAndVerifyJsonAsync(query); + + var dateRangeQuery = DeserializeJsonString(json); + + VerifyQuery(dateRangeQuery); + dateRangeQuery.Format.Should().Be(dateFormat); + + var rangeQuery = DeserializeJsonString(json); + + dateRangeQuery = rangeQuery as DateRangeQuery; + + VerifyQuery(dateRangeQuery); + dateRangeQuery.Format.Should().Be(dateFormat); + } + + [U] + public async Task NumberRangeQuery_SerializesCorrectly() + { + var query = NumberRangeQuery; + + var json = await SerializeAndVerifyJsonAsync(query); + + var numberRangeQuery = DeserializeJsonString(json); + + VerifyQuery(numberRangeQuery); + + var rangeQuery = DeserializeJsonString(json); + + numberRangeQuery = rangeQuery as NumberRangeQuery; + + VerifyQuery(numberRangeQuery); + } + + [U] + public async Task DateRangeQuery_QueryContainer_SerializesCorrectly() + { + var query = Query.Range(DateRangeQueryWithoutFormat); + + var json = await SerializeAndVerifyJsonAsync(query); + + var deserializedQuery = DeserializeJsonString(json); + + deserializedQuery.TryGet(out var dateRangeQuery).Should().BeTrue(); + + VerifyQuery(dateRangeQuery); + } + + [U] + public async Task Fluent_DateRangeQuery_QueryContainer_SerializesCorrectly() + { + var query = new QueryDescriptor(q => q + .Range(r => r + .DateRange(d => d + .Field(Field) + .QueryName(QueryName) + .Boost(1.1f) + .Gte(DateMath.Now.Subtract("1y").RoundTo(DateMathTimeUnit.Month)) + .Lt(DateMath.Now)))); + + var json = await SerializeAndVerifyJsonAsync(query); + + var deserializedQuery = DeserializeJsonString(json); + + deserializedQuery.TryGet(out var dateRangeQuery).Should().BeTrue(); + + VerifyQuery(dateRangeQuery); + } + + [U] + public async Task NumberRangeQuery_QueryContainer_SerializesCorrectly() + { + var query = Query.Range(NumberRangeQuery); + + var json = await SerializeAndVerifyJsonAsync(query); + + var deserializedQuery = DeserializeJsonString(json); + + deserializedQuery.TryGet(out var numberRangeQuery).Should().BeTrue(); + + VerifyQuery(numberRangeQuery); + } + + [U] + public async Task Fluent_NumberRangeQuery_QueryContainer_SerializesCorrectly() + { + var query = new QueryDescriptor(q => q + .Range(r => r + .NumberRange(d => d + .Field(Field) + .QueryName(QueryName) + .Boost(1.1f) + .Gte(100) + .Lt(1000)))); + + var json = await SerializeAndVerifyJsonAsync(query); + + var deserializedQuery = DeserializeJsonString(json); + + deserializedQuery.TryGet(out var numberRangeQuery).Should().BeTrue(); + + VerifyQuery(numberRangeQuery); + } +} diff --git a/tests/Tests/Serialization/SerializerTestBase.cs b/tests/Tests/Serialization/SerializerTestBase.cs index be862d5a0dd..214fec4e0f6 100644 --- a/tests/Tests/Serialization/SerializerTestBase.cs +++ b/tests/Tests/Serialization/SerializerTestBase.cs @@ -130,7 +130,7 @@ static SerializerTestBase() protected static Inferrer Inferrer => _settings.Inferrer; - public static async Task SerializeAndVerifyJson(T data) + public static async Task SerializeAndVerifyJsonAsync(T data) { var serialisedJson = await SerializeAndGetJsonStringAsync(data); await Verifier.VerifyJson(serialisedJson); diff --git a/tests/Tests/Serialization/SuggesterSerializationTests.cs b/tests/Tests/Serialization/SuggesterSerializationTests.cs index a953b5557e8..90f5d07a71f 100644 --- a/tests/Tests/Serialization/SuggesterSerializationTests.cs +++ b/tests/Tests/Serialization/SuggesterSerializationTests.cs @@ -46,6 +46,6 @@ public async Task Suggester_Descriptor_SerializesCorrectly() .Add("my-suggester-1", FieldSuggester.Term(new TermSuggester { Field = Infer.Field(f => f.Description) })) .Add("my-suggester-2", FieldSuggester.Term(new TermSuggester { Field = Infer.Field(f => f.LeadDeveloper) }))); - await SerializeAndVerifyJson(suggester); + await SerializeAndVerifyJsonAsync(suggester); } } diff --git a/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.DateRangeQuery_QueryContainer_SerializesCorrectly.verified.txt b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.DateRangeQuery_QueryContainer_SerializesCorrectly.verified.txt new file mode 100644 index 00000000000..2250e0f67c8 --- /dev/null +++ b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.DateRangeQuery_QueryContainer_SerializesCorrectly.verified.txt @@ -0,0 +1,10 @@ +{ + range: { + my-field: { + boost: 1.1, + gte: now-1y/M, + lt: now, + _name: named_query + } + } +} \ No newline at end of file diff --git a/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.DateRangeQuery_SerializesCorrectly.verified.txt b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.DateRangeQuery_SerializesCorrectly.verified.txt new file mode 100644 index 00000000000..7ffcb581afe --- /dev/null +++ b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.DateRangeQuery_SerializesCorrectly.verified.txt @@ -0,0 +1,8 @@ +{ + my-field: { + boost: 1.1, + gte: now-1y/M, + lt: now, + _name: named_query + } +} \ No newline at end of file diff --git a/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.DateRangeQuery_WithFormat_SerializesCorrectly.verified.txt b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.DateRangeQuery_WithFormat_SerializesCorrectly.verified.txt new file mode 100644 index 00000000000..0b08d417501 --- /dev/null +++ b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.DateRangeQuery_WithFormat_SerializesCorrectly.verified.txt @@ -0,0 +1,9 @@ +{ + my-field: { + boost: 1.1, + format: dd/MM/yyyy||yyyy, + gte: now-1y/M, + lt: now, + _name: named_query + } +} \ No newline at end of file diff --git a/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.Fluent_DateRangeQuery_QueryContainer_SerializesCorrectly.verified.txt b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.Fluent_DateRangeQuery_QueryContainer_SerializesCorrectly.verified.txt new file mode 100644 index 00000000000..2250e0f67c8 --- /dev/null +++ b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.Fluent_DateRangeQuery_QueryContainer_SerializesCorrectly.verified.txt @@ -0,0 +1,10 @@ +{ + range: { + my-field: { + boost: 1.1, + gte: now-1y/M, + lt: now, + _name: named_query + } + } +} \ No newline at end of file diff --git a/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.Fluent_NumberRangeQuery_QueryContainer_SerializesCorrectly.verified.txt b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.Fluent_NumberRangeQuery_QueryContainer_SerializesCorrectly.verified.txt new file mode 100644 index 00000000000..8add8b5ed96 --- /dev/null +++ b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.Fluent_NumberRangeQuery_QueryContainer_SerializesCorrectly.verified.txt @@ -0,0 +1,10 @@ +{ + range: { + my-field: { + boost: 1.1, + gte: 100, + lt: 1000, + _name: named_query + } + } +} \ No newline at end of file diff --git a/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.NumberRangeQuery_QueryContainer_SerializesCorrectly.verified.txt b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.NumberRangeQuery_QueryContainer_SerializesCorrectly.verified.txt new file mode 100644 index 00000000000..8add8b5ed96 --- /dev/null +++ b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.NumberRangeQuery_QueryContainer_SerializesCorrectly.verified.txt @@ -0,0 +1,10 @@ +{ + range: { + my-field: { + boost: 1.1, + gte: 100, + lt: 1000, + _name: named_query + } + } +} \ No newline at end of file diff --git a/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.NumberRangeQuery_SerializesCorrectly.verified.txt b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.NumberRangeQuery_SerializesCorrectly.verified.txt new file mode 100644 index 00000000000..fc1e96110a0 --- /dev/null +++ b/tests/Tests/_VerifySnapshots/RangeQuerySerializationTests.NumberRangeQuery_SerializesCorrectly.verified.txt @@ -0,0 +1,8 @@ +{ + my-field: { + boost: 1.1, + gte: 100, + lt: 1000, + _name: named_query + } +} \ No newline at end of file