diff --git a/src/Elastic.Clients.Elasticsearch/Api/BulkRequest.cs b/src/Elastic.Clients.Elasticsearch/Api/BulkRequest.cs index 40425b6d939..11d00fce89b 100644 --- a/src/Elastic.Clients.Elasticsearch/Api/BulkRequest.cs +++ b/src/Elastic.Clients.Elasticsearch/Api/BulkRequest.cs @@ -13,7 +13,7 @@ namespace Elastic.Clients.Elasticsearch { public partial class BulkRequest : IStreamSerializable { - protected IRequest Self => this; + internal IRequest Self => this; public BulkOperationsCollection Operations { get; set; } diff --git a/src/Elastic.Clients.Elasticsearch/Api/CountRequest.cs b/src/Elastic.Clients.Elasticsearch/Api/CountRequest.cs index 6c34cf2a24e..82b78f99fac 100644 --- a/src/Elastic.Clients.Elasticsearch/Api/CountRequest.cs +++ b/src/Elastic.Clients.Elasticsearch/Api/CountRequest.cs @@ -7,7 +7,7 @@ namespace Elastic.Clients.Elasticsearch { - public partial class CountRequest : CountRequest + public sealed partial class CountRequest : CountRequest { //protected CountRequest TypedSelf => this; diff --git a/src/Elastic.Clients.Elasticsearch/Common/Aggregations/Aggregate.cs b/src/Elastic.Clients.Elasticsearch/Common/Aggregations/Aggregate.cs new file mode 100644 index 00000000000..ffcd45a097a --- /dev/null +++ b/src/Elastic.Clients.Elasticsearch/Common/Aggregations/Aggregate.cs @@ -0,0 +1,16 @@ +// 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. + +namespace Elastic.Clients.Elasticsearch.Aggregations; + +public interface IAggregate { } + +/// +/// Base class for all aggregates. +/// +public abstract class Aggregate : IAggregate +{ +} + + diff --git a/src/Elastic.Clients.Elasticsearch/Common/Aggregations/Aggregation.cs b/src/Elastic.Clients.Elasticsearch/Common/Aggregations/Aggregation.cs new file mode 100644 index 00000000000..881ed8d2f20 --- /dev/null +++ b/src/Elastic.Clients.Elasticsearch/Common/Aggregations/Aggregation.cs @@ -0,0 +1,27 @@ +// 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. + +namespace Elastic.Clients.Elasticsearch.Aggregations; + +public interface IAggregation +{ + string? Name { get; } +} + +/// +/// Base class for all aggregations. +/// +public abstract class Aggregation : IAggregation +{ + public abstract string? Name { get; internal set; } + + //always evaluate to false so that each side of && equation is evaluated + public static bool operator false(Aggregation _) => false; + + //always evaluate to false so that each side of && equation is evaluated + public static bool operator true(Aggregation _) => false; + + public static Aggregation operator &(Aggregation left, Aggregation right) => + new AggregationCombinator(null, left, right); +} diff --git a/src/Elastic.Clients.Elasticsearch/Common/Aggregations/AggregationBase.cs b/src/Elastic.Clients.Elasticsearch/Common/Aggregations/AggregationBase.cs deleted file mode 100644 index dc34f382b84..00000000000 --- a/src/Elastic.Clients.Elasticsearch/Common/Aggregations/AggregationBase.cs +++ /dev/null @@ -1,34 +0,0 @@ -// 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.Collections.Generic; -using System.Text.Json.Serialization; - -namespace Elastic.Clients.Elasticsearch.Aggregations; - -public abstract class AggregationBase -{ - internal AggregationBase(string name) => Name = name; - - /// - /// Custom metadata associated with the aggregation. - /// - [JsonIgnore] - public Dictionary? Meta { get; set; } - - /// - /// The name for this aggregation. - /// - [JsonIgnore] - public string? Name { get; internal set; } - - //always evaluate to false so that each side of && equation is evaluated - public static bool operator false(AggregationBase _) => false; - - //always evaluate to false so that each side of && equation is evaluated - public static bool operator true(AggregationBase _) => false; - - public static AggregationBase operator &(AggregationBase left, AggregationBase right) => - new AggregationCombinator(null, left, right); -} diff --git a/src/Elastic.Clients.Elasticsearch/Common/Aggregations/AggregationCombinator.cs b/src/Elastic.Clients.Elasticsearch/Common/Aggregations/AggregationCombinator.cs index 50974da236b..01341e4f32e 100644 --- a/src/Elastic.Clients.Elasticsearch/Common/Aggregations/AggregationCombinator.cs +++ b/src/Elastic.Clients.Elasticsearch/Common/Aggregations/AggregationCombinator.cs @@ -10,19 +10,20 @@ namespace Elastic.Clients.Elasticsearch.Aggregations; /// /// Combines aggregations into a single list of aggregations. /// -internal class AggregationCombinator : AggregationBase +internal class AggregationCombinator : Aggregation { - public AggregationCombinator(string name, AggregationBase left, AggregationBase right) : base(name) + public AggregationCombinator(string name, Aggregation left, Aggregation right) { AddAggregation(left); AddAggregation(right); + Name = name; } - internal List Aggregations { get; } = new List(); + public override string? Name { get; internal set; } - //internal override void WrapInContainer(AggregationContainer container) { } + internal List Aggregations { get; } = new List(); - private void AddAggregation(AggregationBase agg) + private void AddAggregation(Aggregation agg) { switch (agg) { diff --git a/src/Elastic.Clients.Elasticsearch/Common/Aggregations/AggregationDictionary.cs b/src/Elastic.Clients.Elasticsearch/Common/Aggregations/AggregationDictionary.cs index 276fdfe054e..63a3f2b0b68 100644 --- a/src/Elastic.Clients.Elasticsearch/Common/Aggregations/AggregationDictionary.cs +++ b/src/Elastic.Clients.Elasticsearch/Common/Aggregations/AggregationDictionary.cs @@ -9,7 +9,7 @@ namespace Elastic.Clients.Elasticsearch.Aggregations; /// -/// Describes aggregations that we would like to execute on Elasticsearch. +/// Describes aggregations to execute as part of a search. /// public sealed class AggregationDictionary : IsADictionaryBase { @@ -24,9 +24,9 @@ public AggregationDictionary(Dictionary dictionary public static implicit operator AggregationDictionary(Dictionary dictionary) => new(dictionary); - public static implicit operator AggregationDictionary(AggregationBase aggregator) + public static implicit operator AggregationDictionary(Aggregation aggregator) { - AggregationBase b; + Aggregation b; if (aggregator is AggregationCombinator combinator) { var dict = new AggregationDictionary(); diff --git a/src/Elastic.Clients.Elasticsearch/Common/Query/QueryBase.cs b/src/Elastic.Clients.Elasticsearch/Common/Query/Query.cs similarity index 88% rename from src/Elastic.Clients.Elasticsearch/Common/Query/QueryBase.cs rename to src/Elastic.Clients.Elasticsearch/Common/Query/Query.cs index 514ddabf92c..550cd2a128b 100644 --- a/src/Elastic.Clients.Elasticsearch/Common/Query/QueryBase.cs +++ b/src/Elastic.Clients.Elasticsearch/Common/Query/Query.cs @@ -7,18 +7,6 @@ namespace Elastic.Clients.Elasticsearch.QueryDsl { - // TODO: FieldNameQueryConvertor (see FieldNameQueryFormatter) - public interface IFieldNameQuery - { - Field Field { get; set; } - } - - public abstract class FieldNameQueryBase : QueryBase, IFieldNameQuery - { - [JsonIgnore] - public Field Field { get; set; } - } - public interface IQuery { /// @@ -53,8 +41,8 @@ public interface IQuery /// /// Whether the query should be treated as writable. Used when determining how to combine queries. /// - [JsonIgnore] - bool IsWritable { get; } + //[JsonIgnore] + //bool IsWritable { get; } /// /// The name of the query. Allows you to retrieve for each document what part of the query it matched on. @@ -62,10 +50,10 @@ public interface IQuery //string Name { get; set; } } - public abstract partial class QueryBase : IQuery + public abstract partial class Query : IQuery { - [JsonIgnore] - public bool IsWritable => throw new NotImplementedException(); + //[JsonIgnore] + //public bool IsWritable => throw new NotImplementedException(); ////protected abstract bool Conditionless { get; } //[JsonIgnore] @@ -80,10 +68,10 @@ public abstract partial class QueryBase : IQuery //bool IQuery.Conditionless => Conditionless; //always evaluate to false so that each side of && equation is evaluated - public static bool operator false(QueryBase a) => false; + public static bool operator false(Query a) => false; //always evaluate to false so that each side of && equation is evaluated - public static bool operator true(QueryBase a) => false; + public static bool operator true(Query a) => false; //public static QueryBase operator &(QueryBase leftQuery, QueryBase rightQuery) => Combine(leftQuery, rightQuery, (l, r) => l && r); diff --git a/src/Elastic.Clients.Elasticsearch/Serialization/AggregationContainerSerializationHelper.cs b/src/Elastic.Clients.Elasticsearch/Serialization/AggregationContainerSerializationHelper.cs index 1ffaf579621..29524a65618 100644 --- a/src/Elastic.Clients.Elasticsearch/Serialization/AggregationContainerSerializationHelper.cs +++ b/src/Elastic.Clients.Elasticsearch/Serialization/AggregationContainerSerializationHelper.cs @@ -10,7 +10,7 @@ namespace Elastic.Clients.Elasticsearch internal static class AggregationContainerSerializationHelper { - public static AggregationContainer ReadContainer(ref Utf8JsonReader reader, JsonSerializerOptions options) where T : AggregationBase + public static AggregationContainer ReadContainer(ref Utf8JsonReader reader, JsonSerializerOptions options) where T : Aggregation { var variant = JsonSerializer.Deserialize(ref reader, options); @@ -19,7 +19,7 @@ public static AggregationContainer ReadContainer(ref Utf8JsonReader reader, J return container; } - public static AggregationContainer ReadContainer(string variantName, ref Utf8JsonReader reader, JsonSerializerOptions options) where T : AggregationBase + public static AggregationContainer ReadContainer(string variantName, ref Utf8JsonReader reader, JsonSerializerOptions options) where T : Aggregation { var variant = JsonSerializer.Deserialize(ref reader, options); diff --git a/src/Elastic.Clients.Elasticsearch/Serialization/FieldNameQueryConverterBase.cs b/src/Elastic.Clients.Elasticsearch/Serialization/FieldNameQueryConverterBase.cs deleted file mode 100644 index b07735ccaa7..00000000000 --- a/src/Elastic.Clients.Elasticsearch/Serialization/FieldNameQueryConverterBase.cs +++ /dev/null @@ -1,61 +0,0 @@ -// 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.QueryDsl; - -namespace Elastic.Clients.Elasticsearch -{ - /// - /// A base for converters handling field name query variants. - /// - internal abstract class FieldNameQueryConverterBase : JsonConverter where T : FieldNameQueryBase - { - public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType != JsonTokenType.StartObject) - throw new JsonException($"Unexpected JSON response could not be serialized to {typeof(T)}."); - - reader.Read(); // query type - reader.Read(); // start object - reader.Read(); // field name - var fieldName = reader.GetString(); - reader.Read(); - - var query = ReadInternal(ref reader, typeToConvert, options); - query.Field = fieldName; - - if (reader.TokenType != JsonTokenType.EndObject) - throw new JsonException($"Unexpected JSON response could not be serialized to {typeof(T)}."); - - reader.Read(); - - return query; - } - - public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) - { - if (value.Field is null) - writer.WriteNullValue(); - - if (options.TryGetClientSettings(out var settings)) - { - writer.WriteStartObject(); - writer.WritePropertyName(settings.Inferrer.Field(value.Field)); - WriteInternal(writer, value, options); - writer.WriteEndObject(); - return; - } - - throw new JsonException("Unable to retrieve client settings to infer field."); - } - - internal abstract T? ReadInternal(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options); - internal abstract void WriteInternal(Utf8JsonWriter writer, T value, JsonSerializerOptions options); - } - - -} diff --git a/src/Elastic.Clients.Elasticsearch/Serialization/IsADictionaryConverter.cs b/src/Elastic.Clients.Elasticsearch/Serialization/IsADictionaryConverter.cs index 6d7877ea0b1..7540ac4ae0f 100644 --- a/src/Elastic.Clients.Elasticsearch/Serialization/IsADictionaryConverter.cs +++ b/src/Elastic.Clients.Elasticsearch/Serialization/IsADictionaryConverter.cs @@ -54,3 +54,7 @@ public override void Write(Utf8JsonWriter writer, TType value, JsonSerializerOpt } +internal interface IUnionVerifiable +{ + bool IsSuccessful { get; } +} diff --git a/src/Elastic.Clients.Elasticsearch/Serialization/SourceSerialisation.cs b/src/Elastic.Clients.Elasticsearch/Serialization/SourceSerialisation.cs index 0c78289c266..a9470428235 100644 --- a/src/Elastic.Clients.Elasticsearch/Serialization/SourceSerialisation.cs +++ b/src/Elastic.Clients.Elasticsearch/Serialization/SourceSerialisation.cs @@ -42,16 +42,16 @@ public static void SerializeParams(T toSerialize, Utf8JsonWriter writer, IEla JsonSerializer.Serialize(writer, toSerialize, options); } - public static void DeserializeParams(ref Utf8JsonReader reader, IElasticsearchClientSettings settings) + public static T DeserializeParams(ref Utf8JsonReader reader, IElasticsearchClientSettings settings) { if (settings.Experimental.UseSourceSerializerForScriptParameters) { - Deserialize(ref reader, settings); - return; + var result = Deserialize(ref reader, settings); + return result; } _ = settings.RequestResponseSerializer.TryGetJsonSerializerOptions(out var options); - JsonSerializer.Deserialize(ref reader, options); + return JsonSerializer.Deserialize(ref reader, options); } public static void Serialize(T toSerialize, Utf8JsonWriter writer, IElasticsearchClientSettings settings) => diff --git a/src/Elastic.Clients.Elasticsearch/Serialization/TermsAggregateSerializationHelper.cs b/src/Elastic.Clients.Elasticsearch/Serialization/TermsAggregateSerializationHelper.cs index 1cfd344f638..06abf039ab1 100644 --- a/src/Elastic.Clients.Elasticsearch/Serialization/TermsAggregateSerializationHelper.cs +++ b/src/Elastic.Clients.Elasticsearch/Serialization/TermsAggregateSerializationHelper.cs @@ -15,7 +15,7 @@ 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(ref Utf8JsonReader reader, JsonSerializerOptions options, out AggregateBase? aggregate) + public static bool TryDeserialiseTermsAggregate(ref Utf8JsonReader reader, JsonSerializerOptions options, out IAggregate? aggregate) { aggregate = null; diff --git a/src/Elastic.Clients.Elasticsearch/Serialization/UnionConverter.cs b/src/Elastic.Clients.Elasticsearch/Serialization/UnionConverter.cs index 86062c333c0..edf5251fafa 100644 --- a/src/Elastic.Clients.Elasticsearch/Serialization/UnionConverter.cs +++ b/src/Elastic.Clients.Elasticsearch/Serialization/UnionConverter.cs @@ -12,9 +12,13 @@ namespace Elastic.Clients.Elasticsearch; internal sealed class UnionConverter : JsonConverterFactory { + // Because converters registered on JsonSerializerOptions take priority over the JsonConverter attribute on the type, we need a way to + // mark those types we don't want to use the default union converter. This set is used for that purpose, until a better option can be + // found. private static readonly HashSet TypesToSkip = new() { - typeof(SourceConfig) + typeof(SourceConfig), + typeof(Script) }; public override bool CanConvert(Type typeToConvert) => !TypesToSkip.Contains(typeToConvert) && @@ -67,27 +71,23 @@ private class DerivedUnionConverterInner : JsonConverter< { // TODO - Aggregate Exception if both fail - //var requiresEndObject = false; - var readerCopy = reader; - //if (readerCopy.TokenType == JsonTokenType.StartObject) - //{ - // requiresEndObject = true; - // readerCopy.Read(); - //} - try { var itemOne = JsonSerializer.Deserialize(ref readerCopy, options); - if (itemOne is not null) + if (itemOne is IUnionVerifiable verifiable) + { + if (verifiable.IsSuccessful) + { + reader = readerCopy; + return (TType)Activator.CreateInstance(typeof(TType), itemOne); + } + } + else if (itemOne is not null) { - //if (requiresEndObject) - // readerCopy.Read(); - reader = readerCopy; - return (TType)Activator.CreateInstance(typeof(TType), itemOne); } } @@ -108,9 +108,6 @@ private class DerivedUnionConverterInner : JsonConverter< if (itemTwo is not null) { - //if (requiresEndObject) - // reader.Read(); - return (TType)Activator.CreateInstance(typeof(TType), itemTwo); } } diff --git a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregateDictionary.cs b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregateDictionary.cs index 26426e5874c..aa10d15f500 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregateDictionary.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregateDictionary.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.Linq; namespace Elastic.Clients.Elasticsearch.Aggregations @@ -37,18 +38,35 @@ public TermsAggregate Terms(string key) return null; } + Buckets> buckets = null; + switch (agg) { case EmptyTermsAggregate empty: return new TermsAggregate { - Buckets = Array.Empty>().ToReadOnlyCollection(), + Buckets = new Buckets>(Array.Empty>()), Meta = empty.Meta, DocCountErrorUpperBound = empty.DocCountErrorUpperBound, SumOtherDocCount = empty.SumOtherDocCount }; + case StringTermsAggregate stringTerms: - var buckets = stringTerms.Buckets.Select(b => new TermsBucket { DocCount = b.DocCount, DocCountError = b.DocCountError, Key = GetKeyFromBucketKey(b.Key), KeyAsString = b.Key }).ToReadOnlyCollection(); + stringTerms.Buckets.Match(a => + { + var dict = new Dictionary>(); + foreach (var item in a) + { + var key = item.Key; + var value = item.Value; + dict.Add(key, new TermsBucket { DocCount = value.DocCount, DocCountError = value.DocCountError, Key = GetKeyFromBucketKey(value.Key), KeyAsString = value.Key }); + } + buckets = new(dict); + }, a => + { + buckets = new(a.Select(b => new TermsBucket { DocCount = b.DocCount, DocCountError = b.DocCountError, Key = GetKeyFromBucketKey(b.Key), KeyAsString = b.Key }).ToReadOnlyCollection()); + }); + return new TermsAggregate { Buckets = buckets, @@ -56,20 +74,50 @@ public TermsAggregate Terms(string key) DocCountErrorUpperBound = stringTerms.DocCountErrorUpperBound, SumOtherDocCount = stringTerms.SumOtherDocCount }; + case DoubleTermsAggregate doubleTerms: - var doubleTermsBuckets = doubleTerms.Buckets.Select(b => new TermsBucket { DocCount = b.DocCount, DocCountError = b.DocCountError, Key = GetKeyFromBucketKey(b.Key), KeyAsString = b.KeyAsString }).ToReadOnlyCollection(); + doubleTerms.Buckets.Match(a => + { + var dict = new Dictionary>(); + foreach (var item in a) + { + var key = item.Key; + var value = item.Value; + dict.Add(key, new TermsBucket { DocCount = value.DocCount, DocCountError = value.DocCountError, Key = GetKeyFromBucketKey(value.Key), KeyAsString = value.KeyAsString }); + } + buckets = new(dict); + }, a => + { + buckets = new(a.Select(b => new TermsBucket { DocCount = b.DocCount, DocCountError = b.DocCountError, Key = GetKeyFromBucketKey(b.Key), KeyAsString = b.KeyAsString }).ToReadOnlyCollection()); + }); + return new TermsAggregate { - Buckets = doubleTermsBuckets, + Buckets = buckets, Meta = doubleTerms.Meta, DocCountErrorUpperBound = doubleTerms.DocCountErrorUpperBound, SumOtherDocCount = doubleTerms.SumOtherDocCount }; + case LongTermsAggregate longTerms: - var longTermsBuckets = longTerms.Buckets.Select(b => new TermsBucket { DocCount = b.DocCount, DocCountError = b.DocCountError, Key = GetKeyFromBucketKey(b.Key), KeyAsString = b.KeyAsString }).ToReadOnlyCollection(); + longTerms.Buckets.Match(a => + { + var dict = new Dictionary>(); + foreach (var item in a) + { + var key = item.Key; + var value = item.Value; + dict.Add(key, new TermsBucket { DocCount = value.DocCount, DocCountError = value.DocCountError, Key = GetKeyFromBucketKey(value.Key), KeyAsString = value.KeyAsString }); + } + buckets = new(dict); + }, a => + { + buckets = new(a.Select(b => new TermsBucket { DocCount = b.DocCount, DocCountError = b.DocCountError, Key = GetKeyFromBucketKey(b.Key), KeyAsString = b.KeyAsString }).ToReadOnlyCollection()); + }); + return new TermsAggregate { - Buckets = longTermsBuckets, + Buckets = buckets, Meta = longTerms.Meta, DocCountErrorUpperBound = longTerms.DocCountErrorUpperBound, SumOtherDocCount = longTerms.SumOtherDocCount diff --git a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregateDictionaryConverter.cs b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregateDictionaryConverter.cs index 560d19a2e6d..cf6ac4355e7 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregateDictionaryConverter.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregateDictionaryConverter.cs @@ -13,7 +13,7 @@ internal sealed class AggregateDictionaryConverter : JsonConverter(); + var dictionary = new Dictionary(); if (reader.TokenType != JsonTokenType.StartObject) return new AggregateDictionary(dictionary); @@ -33,7 +33,7 @@ internal sealed class AggregateDictionaryConverter : JsonConverter dictionary, string name) + public static void ReadAggregate(ref Utf8JsonReader reader, JsonSerializerOptions options, Dictionary dictionary, string name) { var nameParts = name.Split('#'); diff --git a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregationContainer.cs b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregationContainer.cs index 721773685d0..43074c11351 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregationContainer.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/AggregationContainer.cs @@ -30,7 +30,7 @@ public partial class AggregationContainer JsonSerializer.Serialize(writer, descriptor, options); }; - public static implicit operator AggregationContainer(AggregationBase aggregator) + public static implicit operator AggregationContainer(Aggregation aggregator) { if (aggregator == null) return null; @@ -44,7 +44,7 @@ public static implicit operator AggregationContainer(AggregationBase aggregator) //aggregator.WrapInContainer(container); - var bucket = aggregator as BucketAggregationBase; + //var bucket = aggregator as BucketAggregationBase; //container.Aggregations = bucket?.Aggregations; diff --git a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/EmptyTermsAggregate.cs b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/EmptyTermsAggregate.cs index b6cd25e4383..42cf200b0a4 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/EmptyTermsAggregate.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/EmptyTermsAggregate.cs @@ -2,9 +2,27 @@ // 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.Collections.Generic; +using System.Text.Json.Serialization; + namespace Elastic.Clients.Elasticsearch.Aggregations { - public class EmptyTermsAggregate : TermsAggregateBase + public sealed class EmptyTermsAggregate : IAggregate { + [JsonInclude] + [JsonPropertyName("doc_count_error_upper_bound")] + public long? DocCountErrorUpperBound { get; init; } + + [JsonInclude] + [JsonPropertyName("sum_other_doc_count")] + public long SumOtherDocCount { get; init; } + + [JsonInclude] + [JsonPropertyName("buckets")] + public Buckets> Buckets { get; init; } + + [JsonInclude] + [JsonPropertyName("meta")] + public Dictionary? Meta { get; init; } } } diff --git a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/EmptyTermsBucket.cs b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/EmptyTermsBucket.cs index 2eee452d59f..979fbf3949d 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/EmptyTermsBucket.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/EmptyTermsBucket.cs @@ -4,5 +4,5 @@ namespace Elastic.Clients.Elasticsearch.Aggregations { - public class EmptyTermsBucket { } + public sealed class EmptyTermsBucket { } } diff --git a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/MultiBucketAggregateBase.cs b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/MultiBucketAggregateBase.cs deleted file mode 100644 index c6043390595..00000000000 --- a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/MultiBucketAggregateBase.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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.Collections.Generic; -using System.Text.Json.Serialization; - -namespace Elastic.Clients.Elasticsearch.Aggregations -{ - public abstract partial class MultiBucketAggregateBase - { - [JsonInclude] - [JsonPropertyName("buckets")] - public IReadOnlyCollection Buckets { get; init; } - } -} diff --git a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/TermsAggregate.cs b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/TermsAggregate.cs index e69698d570b..a0642717d62 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/TermsAggregate.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/TermsAggregate.cs @@ -2,9 +2,27 @@ // 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.Collections.Generic; +using System.Text.Json.Serialization; + namespace Elastic.Clients.Elasticsearch.Aggregations { - public class TermsAggregate : TermsAggregateBase> + public sealed class TermsAggregate : IAggregate { + [JsonInclude] + [JsonPropertyName("doc_count_error_upper_bound")] + public long? DocCountErrorUpperBound { get; init; } + + [JsonInclude] + [JsonPropertyName("sum_other_doc_count")] + public long SumOtherDocCount { get; init; } + + [JsonInclude] + [JsonPropertyName("buckets")] + public Buckets> Buckets { get; init; } + + [JsonInclude] + [JsonPropertyName("meta")] + public Dictionary? Meta { get; init; } } } diff --git a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/TermsBucket.cs b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/TermsBucket.cs index bc9649133b6..3d6d063bf6a 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Aggregations/TermsBucket.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Aggregations/TermsBucket.cs @@ -2,10 +2,24 @@ // 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.Json.Serialization; + namespace Elastic.Clients.Elasticsearch.Aggregations; -public class TermsBucket : TermsBucketBase +public sealed class TermsBucket { public TKey Key { get; init; } public string? KeyAsString { get; init; } + + [JsonInclude] + [JsonPropertyName("doc_count_error")] + public long? DocCountError { get; init; } + + [JsonInclude] + [JsonPropertyName("aggregations")] + public Elastic.Clients.Elasticsearch.Aggregations.AggregateDictionary Aggregations { get; init; } + + [JsonInclude] + [JsonPropertyName("doc_count")] + public long DocCount { get; init; } } diff --git a/src/Elastic.Clients.Elasticsearch/Types/AsyncSearch/AsyncSearch.cs b/src/Elastic.Clients.Elasticsearch/Types/AsyncSearch/AsyncSearch.cs index d9ab360f2f3..b774c25c5cf 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/AsyncSearch/AsyncSearch.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/AsyncSearch/AsyncSearch.cs @@ -10,12 +10,21 @@ namespace Elastic.Clients.Elasticsearch.AsyncSearch; public partial class AsyncSearch { + /// + /// Shortcut to the hits returned for this search. + /// [JsonIgnore] public IReadOnlyCollection> Hits => HitsMetadata.Hits; + /// + /// The source documents from the matching hits. + /// [JsonIgnore] public IReadOnlyCollection Documents => HitsMetadata.Hits.Select(s => s.Source).ToReadOnlyCollection(); + /// + /// The total number of hits returned for this search. + /// [JsonIgnore] public long Total => HitsMetadata?.Total?.Value ?? -1; } diff --git a/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateBody.cs b/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateBody.cs index f57db213f72..e9912c16516 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateBody.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateBody.cs @@ -12,7 +12,7 @@ internal class BulkUpdateBody : BulkUpdateBodyBase public TPartialUpdate PartialUpdate { get; set; } - public ScriptBase Script { get; set; } + public Script Script { get; set; } public bool? ScriptedUpsert { get; set; } diff --git a/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateOperation.cs b/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateOperation.cs index 508dd47f088..b26cc83b04d 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateOperation.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateOperation.cs @@ -44,7 +44,7 @@ public BulkUpdateOperation(TDocument idFrom, TPartialDocument update, bool useId public TDocument IdFrom { get; set; } [JsonIgnore] - public ScriptBase Script { get; set; } + public Script Script { get; set; } [JsonIgnore] public bool? ScriptedUpsert { get; set; } @@ -94,13 +94,13 @@ public static class BulkUpdateOperationFactory public static BulkUpdateOperationWithPartial WithPartial(Id id, IndexName index, TPartial partialDocument) => new(id, index, partialDocument); - public static BulkUpdateOperationWithScript WithScript(Id id, IndexName index, ScriptBase script) => new(id, index, script); + public static BulkUpdateOperationWithScript WithScript(Id id, IndexName index, Script script) => new(id, index, script); - public static BulkUpdateOperationWithScript WithScript(Id id, IndexName index, ScriptBase script, TDocument upsert) => new(upsert, id, index, script); + public static BulkUpdateOperationWithScript WithScript(Id id, IndexName index, Script script, TDocument upsert) => new(upsert, id, index, script); - public static BulkUpdateOperationWithScript WithScript(Id id, ScriptBase script, TDocument upsert) => new(upsert, id, script); + public static BulkUpdateOperationWithScript WithScript(Id id, Script script, TDocument upsert) => new(upsert, id, script); - public static BulkUpdateOperationWithScript WithScript(ScriptBase script, TDocument upsert) => new(upsert, new Id(upsert), script); + public static BulkUpdateOperationWithScript WithScript(Script script, TDocument upsert) => new(upsert, new Id(upsert), script); - public static BulkUpdateOperationWithScript WithScript(Id id, ScriptBase script) => new(id, script); + public static BulkUpdateOperationWithScript WithScript(Id id, Script script) => new(id, script); } diff --git a/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateOperationDescriptor.cs b/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateOperationDescriptor.cs index 1df14639d4f..786988de430 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateOperationDescriptor.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateOperationDescriptor.cs @@ -26,7 +26,7 @@ public BulkUpdateOperationDescriptor() { } private bool? _docAsUpsert; private bool? _scriptedUpsert; private int? _retriesOnConflict; - private ScriptBase _script; + private Script _script; private Union _source; private Action _inlineScriptAction; @@ -66,7 +66,7 @@ public BulkUpdateOperationDescriptor Script(Action< return Assign(configure, (a, v) => a._storedScriptIdAction = v); } - public BulkUpdateOperationDescriptor Script(ScriptBase script) + public BulkUpdateOperationDescriptor Script(Script script) { _inlineScriptAction = null; _storedScriptIdAction = null; diff --git a/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateOperationWithScript.cs b/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateOperationWithScript.cs index 8e055b45d37..7d2fb98b4b2 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateOperationWithScript.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Bulk/BulkUpdateOperationWithScript.cs @@ -10,13 +10,13 @@ namespace Elastic.Clients.Elasticsearch { public class BulkUpdateOperationWithScript : BulkUpdateOperationBase { - public BulkUpdateOperationWithScript(Id id, ScriptBase script) + public BulkUpdateOperationWithScript(Id id, Script script) { Id = id; Script = script; } - public BulkUpdateOperationWithScript(Id id, IndexName index, ScriptBase script) + public BulkUpdateOperationWithScript(Id id, IndexName index, Script script) { Id = id; Index = index; @@ -24,7 +24,7 @@ public BulkUpdateOperationWithScript(Id id, IndexName index, ScriptBase script) } [JsonIgnore] - public ScriptBase Script { get; set; } + public Script Script { get; set; } protected override string Operation => "update"; @@ -41,9 +41,9 @@ protected override void BeforeSerialize(IElasticsearchClientSettings settings) public sealed class BulkUpdateOperationWithScript : BulkUpdateOperationWithScript { - public BulkUpdateOperationWithScript(TDocument upsert, Id id, ScriptBase script) : base(id, script) => Upsert = upsert; + public BulkUpdateOperationWithScript(TDocument upsert, Id id, Script script) : base(id, script) => Upsert = upsert; - public BulkUpdateOperationWithScript(TDocument upsert, Id id, IndexName index, ScriptBase script) : base(id, index, script) => Upsert = upsert; + public BulkUpdateOperationWithScript(TDocument upsert, Id id, IndexName index, Script script) : base(id, index, script) => Upsert = upsert; [JsonIgnore] public TDocument Upsert { get; set; } diff --git a/src/Elastic.Clients.Elasticsearch/Types/Bulk/ScriptedBulkUpdateBody.cs b/src/Elastic.Clients.Elasticsearch/Types/Bulk/ScriptedBulkUpdateBody.cs index 4b1c3d2b16f..64f22319b1e 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Bulk/ScriptedBulkUpdateBody.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Bulk/ScriptedBulkUpdateBody.cs @@ -8,7 +8,7 @@ namespace Elastic.Clients.Elasticsearch { internal class ScriptedBulkUpdateBody : BulkUpdateBodyBase { - public ScriptBase Script { get; set; } + public Script Script { get; set; } protected override void SerializeProperties(Utf8JsonWriter writer, JsonSerializerOptions options, IElasticsearchClientSettings settings) { diff --git a/src/Elastic.Clients.Elasticsearch/Types/Documents/MultiSearch/MultiSearchRequest.cs b/src/Elastic.Clients.Elasticsearch/Types/Documents/MultiSearch/MultiSearchRequest.cs index 939f89596f4..c8a1b0888ae 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/Documents/MultiSearch/MultiSearchRequest.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/Documents/MultiSearch/MultiSearchRequest.cs @@ -70,18 +70,6 @@ async Task IStreamSerializable.SerializeAsync(Stream stream, IElasticsearchClien } } - public partial class ResponseBody - { - [JsonIgnore] - public IReadOnlyCollection> Hits => HitsMetadata.Hits; - - [JsonIgnore] - public IReadOnlyCollection Documents => HitsMetadata.Hits.Select(s => s.Source).ToReadOnlyCollection(); - - [JsonIgnore] - public long Total => HitsMetadata?.Total?.Value ?? -1; - } - public partial class MultiSearchResponse { public override bool IsValid => base.IsValid && (Responses?.All(b => b.Item1 is not null && b.Item1.Status == 200) ?? true); diff --git a/src/Elastic.Clients.Elasticsearch/Types/MultiSearchItem.cs b/src/Elastic.Clients.Elasticsearch/Types/MultiSearchItem.cs new file mode 100644 index 00000000000..bb0ab128deb --- /dev/null +++ b/src/Elastic.Clients.Elasticsearch/Types/MultiSearchItem.cs @@ -0,0 +1,21 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Text.Json.Serialization; + +namespace Elastic.Clients.Elasticsearch; + +public partial class MultiSearchItem +{ + [JsonIgnore] + public IReadOnlyCollection> Hits => HitsMetadata.Hits; + + [JsonIgnore] + public IReadOnlyCollection Documents => HitsMetadata.Hits.Select(s => s.Source).ToReadOnlyCollection(); + + [JsonIgnore] + public long Total => HitsMetadata?.Total?.Value ?? -1; +} diff --git a/src/Elastic.Clients.Elasticsearch/Types/ScriptBase.cs b/src/Elastic.Clients.Elasticsearch/Types/ScriptBase.cs index d3cf605dfd0..4360134fe50 100644 --- a/src/Elastic.Clients.Elasticsearch/Types/ScriptBase.cs +++ b/src/Elastic.Clients.Elasticsearch/Types/ScriptBase.cs @@ -8,52 +8,57 @@ namespace Elastic.Clients.Elasticsearch; -[JsonConverter(typeof(ScriptBaseConverter))] -public abstract partial class ScriptBase -{ -} - -internal sealed class ScriptBaseConverter : JsonConverter -{ - public override ScriptBase? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var readAheadCopy = reader; - - if (readAheadCopy.TokenType == JsonTokenType.String) - { - var source = reader.GetString(); - return new InlineScript(source); - } - - readAheadCopy.Read(); // { - - if (readAheadCopy.TokenType != JsonTokenType.PropertyName) - throw new JsonException("Unexpected token type"); - - if (readAheadCopy.ValueTextEquals("params")) - { - while (readAheadCopy.Read() && readAheadCopy.TokenType != JsonTokenType.EndObject) - { - } - - readAheadCopy.Read(); - } - - if (readAheadCopy.ValueTextEquals("id")) - return JsonSerializer.Deserialize(ref reader, options); - - return JsonSerializer.Deserialize(ref reader, options); - } - - public override void Write(Utf8JsonWriter writer, ScriptBase value, JsonSerializerOptions options) - { - if (value is InlineScript scriptSort) - JsonSerializer.Serialize(writer, scriptSort, options); - - else if (value is StoredScriptId storedScript) - JsonSerializer.Serialize(writer, storedScript, options); - - else - throw new JsonException("Unsupported script implementation"); - } -} +//public interface IScript { } + +///// +///// Base class for scripts +///// +//[JsonConverter(typeof(ScriptBaseConverter))] +//public abstract class Script : IScript +//{ +//} + +//internal sealed class ScriptBaseConverter : JsonConverter