/* SPDX-License-Identifier: Apache-2.0 * * The OpenSearch Contributors require contributions made to * this file be licensed under the Apache-2.0 license or a * compatible open source license. */ /* * Modifications Copyright OpenSearch Contributors. See * GitHub history for details. * * Licensed to Elasticsearch B.V. under one or more contributor * license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch B.V. licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using OpenSearch.Net.Utf8Json; namespace OpenSearch.Client { /// /// Describes aggregations that we would like to execute on OpenSearch. /// /// In OSC Aggregation always refers to an aggregation /// sent to OpenSearch and an Aggregate describes an aggregation returned from OpenSearch. /// [JsonFormatter(typeof(AggregationDictionaryFormatter))] public class AggregationDictionary : IsADictionaryBase { public AggregationDictionary() { } public AggregationDictionary(IDictionary container) : base(container) { } public AggregationDictionary(Dictionary container) : base(container.ToDictionary(kv => kv.Key, kv => (IAggregationContainer)kv.Value)) { } public static implicit operator AggregationDictionary(Dictionary container) => new AggregationDictionary(container); public static implicit operator AggregationDictionary(Dictionary container) => new AggregationDictionary(container); public static implicit operator AggregationDictionary(AggregationBase aggregator) { IAggregation b; if (aggregator is AggregationCombinator combinator) { var dict = new AggregationDictionary(); foreach (var agg in combinator.Aggregations) { b = agg; if (b.Name.IsNullOrEmpty()) throw new ArgumentException($"{aggregator.GetType().Name} .Name is not set!"); dict.Add(b.Name, agg); } return dict; } b = aggregator; if (b.Name.IsNullOrEmpty()) throw new ArgumentException($"{aggregator.GetType().Name} .Name is not set!"); return new AggregationDictionary { { b.Name, aggregator } }; } public void Add(string key, AggregationContainer value) => BackingDictionary.Add(ValidateKey(key), value); protected override string ValidateKey(string key) { if (AggregateFormatter.AllReservedAggregationNames.Contains(key)) throw new ArgumentException( string.Format(AggregateFormatter.UsingReservedAggNameFormat, key), nameof(key)); return key; } } internal class AggregationDictionaryFormatter : IJsonFormatter { private static readonly VerbatimDictionaryInterfaceKeysFormatter DictionaryKeysFormatter = new VerbatimDictionaryInterfaceKeysFormatter(); public AggregationDictionary Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver) => new AggregationDictionary(DictionaryKeysFormatter.Deserialize(ref reader, formatterResolver)); public void Serialize(ref JsonWriter writer, AggregationDictionary value, IJsonFormatterResolver formatterResolver) => DictionaryKeysFormatter.Serialize(ref writer, value, formatterResolver); } [InterfaceDataContract] [ReadAs(typeof(AggregationContainer))] public interface IAggregationContainer { [DataMember(Name = "adjacency_matrix")] IAdjacencyMatrixAggregation AdjacencyMatrix { get; set; } [DataMember(Name = "aggs")] AggregationDictionary Aggregations { get; set; } [DataMember(Name = "avg")] IAverageAggregation Average { get; set; } [DataMember(Name = "avg_bucket")] IAverageBucketAggregation AverageBucket { get; set; } [DataMember(Name = "bucket_script")] IBucketScriptAggregation BucketScript { get; set; } [DataMember(Name = "bucket_selector")] IBucketSelectorAggregation BucketSelector { get; set; } [DataMember(Name = "bucket_sort")] IBucketSortAggregation BucketSort { get; set; } [DataMember(Name = "cardinality")] ICardinalityAggregation Cardinality { get; set; } [DataMember(Name = "children")] IChildrenAggregation Children { get; set; } [DataMember(Name = "composite")] ICompositeAggregation Composite { get; set; } [DataMember(Name = "cumulative_sum")] ICumulativeSumAggregation CumulativeSum { get; set; } [DataMember(Name = "date_histogram")] IDateHistogramAggregation DateHistogram { get; set; } [DataMember(Name ="auto_date_histogram")] IAutoDateHistogramAggregation AutoDateHistogram { get; set; } [DataMember(Name = "date_range")] IDateRangeAggregation DateRange { get; set; } [DataMember(Name = "derivative")] IDerivativeAggregation Derivative { get; set; } [DataMember(Name = "diversified_sampler")] IDiversifiedSamplerAggregation DiversifiedSampler { get; set; } [DataMember(Name = "extended_stats")] IExtendedStatsAggregation ExtendedStats { get; set; } [DataMember(Name = "extended_stats_bucket")] IExtendedStatsBucketAggregation ExtendedStatsBucket { get; set; } [DataMember(Name = "filter")] IFilterAggregation Filter { get; set; } [DataMember(Name = "filters")] IFiltersAggregation Filters { get; set; } [DataMember(Name = "geo_bounds")] IGeoBoundsAggregation GeoBounds { get; set; } [DataMember(Name = "geo_centroid")] IGeoCentroidAggregation GeoCentroid { get; set; } [DataMember(Name = "geo_distance")] IGeoDistanceAggregation GeoDistance { get; set; } [DataMember(Name = "geohash_grid")] IGeoHashGridAggregation GeoHash { get; set; } [DataMember(Name = "geo_line")] IGeoLineAggregation GeoLine { get; set; } [DataMember(Name = "geotile_grid")] IGeoTileGridAggregation GeoTile { get; set; } [DataMember(Name = "global")] IGlobalAggregation Global { get; set; } [DataMember(Name = "histogram")] IHistogramAggregation Histogram { get; set; } [DataMember(Name = "ip_range")] IIpRangeAggregation IpRange { get; set; } [DataMember(Name = "matrix_stats")] IMatrixStatsAggregation MatrixStats { get; set; } [DataMember(Name = "max")] IMaxAggregation Max { get; set; } [DataMember(Name = "max_bucket")] IMaxBucketAggregation MaxBucket { get; set; } [DataMember(Name = "meta")] [JsonFormatter(typeof(VerbatimDictionaryInterfaceKeysFormatter))] IDictionary Meta { get; set; } [DataMember(Name = "min")] IMinAggregation Min { get; set; } [DataMember(Name = "min_bucket")] IMinBucketAggregation MinBucket { get; set; } [DataMember(Name = "missing")] IMissingAggregation Missing { get; set; } [DataMember(Name = "moving_avg")] IMovingAverageAggregation MovingAverage { get; set; } [DataMember(Name = "moving_fn")] IMovingFunctionAggregation MovingFunction { get; set; } [DataMember(Name = "nested")] INestedAggregation Nested { get; set; } /// [DataMember(Name = "parent")] IParentAggregation Parent { get; set; } [DataMember(Name = "percentile_ranks")] IPercentileRanksAggregation PercentileRanks { get; set; } [DataMember(Name = "percentiles")] IPercentilesAggregation Percentiles { get; set; } [DataMember(Name = "percentiles_bucket")] IPercentilesBucketAggregation PercentilesBucket { get; set; } [DataMember(Name = "range")] IRangeAggregation Range { get; set; } [DataMember(Name = "rare_terms")] IRareTermsAggregation RareTerms { get; set; } [DataMember(Name = "reverse_nested")] IReverseNestedAggregation ReverseNested { get; set; } [DataMember(Name = "sampler")] ISamplerAggregation Sampler { get; set; } [DataMember(Name = "scripted_metric")] IScriptedMetricAggregation ScriptedMetric { get; set; } [DataMember(Name = "serial_diff")] ISerialDifferencingAggregation SerialDifferencing { get; set; } [DataMember(Name = "significant_terms")] ISignificantTermsAggregation SignificantTerms { get; set; } [DataMember(Name = "significant_text")] ISignificantTextAggregation SignificantText { get; set; } [DataMember(Name = "stats")] IStatsAggregation Stats { get; set; } [DataMember(Name = "stats_bucket")] IStatsBucketAggregation StatsBucket { get; set; } [DataMember(Name = "sum")] ISumAggregation Sum { get; set; } [DataMember(Name = "sum_bucket")] ISumBucketAggregation SumBucket { get; set; } [DataMember(Name = "terms")] ITermsAggregation Terms { get; set; } [DataMember(Name = "top_hits")] ITopHitsAggregation TopHits { get; set; } [DataMember(Name = "value_count")] IValueCountAggregation ValueCount { get; set; } [DataMember(Name = "weighted_avg")] IWeightedAverageAggregation WeightedAverage { get; set; } [DataMember(Name = "median_absolute_deviation")] IMedianAbsoluteDeviationAggregation MedianAbsoluteDeviation { get; set; } [DataMember(Name = "multi_terms")] IMultiTermsAggregation MultiTerms { get; set; } [DataMember(Name = "variable_width_histogram")] IVariableWidthHistogramAggregation VariableWidthHistogram { get; set; } void Accept(IAggregationVisitor visitor); } public class AggregationContainer : IAggregationContainer { public IAdjacencyMatrixAggregation AdjacencyMatrix { get; set; } // This is currently used to support deserializing the response from SQL Translate, // which forms a response which uses "aggregations", rather than "aggs". Longer term // it would be preferred to address that in OpenSearch itself. [DataMember(Name = "aggregations")] private AggregationDictionary _aggs; // ReSharper disable once ConvertToAutoProperty public AggregationDictionary Aggregations { get => _aggs; set => _aggs = value; } public IAverageAggregation Average { get; set; } public IAverageBucketAggregation AverageBucket { get; set; } public IBucketScriptAggregation BucketScript { get; set; } public IBucketSelectorAggregation BucketSelector { get; set; } public IBucketSortAggregation BucketSort { get; set; } public ICardinalityAggregation Cardinality { get; set; } public IChildrenAggregation Children { get; set; } public ICompositeAggregation Composite { get; set; } public ICumulativeSumAggregation CumulativeSum { get; set; } public IDateHistogramAggregation DateHistogram { get; set; } public IAutoDateHistogramAggregation AutoDateHistogram { get; set; } public IDateRangeAggregation DateRange { get; set; } public IDerivativeAggregation Derivative { get; set; } public IDiversifiedSamplerAggregation DiversifiedSampler { get; set; } public IExtendedStatsAggregation ExtendedStats { get; set; } public IExtendedStatsBucketAggregation ExtendedStatsBucket { get; set; } public IFilterAggregation Filter { get; set; } public IFiltersAggregation Filters { get; set; } public IGeoBoundsAggregation GeoBounds { get; set; } public IGeoCentroidAggregation GeoCentroid { get; set; } public IGeoDistanceAggregation GeoDistance { get; set; } public IGeoHashGridAggregation GeoHash { get; set; } public IGeoLineAggregation GeoLine { get; set; } public IGeoTileGridAggregation GeoTile { get; set; } public IGlobalAggregation Global { get; set; } public IHistogramAggregation Histogram { get; set; } public IIpRangeAggregation IpRange { get; set; } public IMatrixStatsAggregation MatrixStats { get; set; } public IMaxAggregation Max { get; set; } public IMaxBucketAggregation MaxBucket { get; set; } public IDictionary Meta { get; set; } public IMinAggregation Min { get; set; } public IMinBucketAggregation MinBucket { get; set; } public IMissingAggregation Missing { get; set; } public IMovingAverageAggregation MovingAverage { get; set; } public IMovingFunctionAggregation MovingFunction { get; set; } public INestedAggregation Nested { get; set; } /// public IParentAggregation Parent { get; set; } public IPercentileRanksAggregation PercentileRanks { get; set; } public IPercentilesAggregation Percentiles { get; set; } public IPercentilesBucketAggregation PercentilesBucket { get; set; } public IRangeAggregation Range { get; set; } public IRareTermsAggregation RareTerms { get; set; } public IReverseNestedAggregation ReverseNested { get; set; } public ISamplerAggregation Sampler { get; set; } public IScriptedMetricAggregation ScriptedMetric { get; set; } public ISerialDifferencingAggregation SerialDifferencing { get; set; } public ISignificantTermsAggregation SignificantTerms { get; set; } public ISignificantTextAggregation SignificantText { get; set; } public IStatsAggregation Stats { get; set; } public IStatsBucketAggregation StatsBucket { get; set; } public ISumAggregation Sum { get; set; } public ISumBucketAggregation SumBucket { get; set; } public ITermsAggregation Terms { get; set; } public ITopHitsAggregation TopHits { get; set; } public IValueCountAggregation ValueCount { get; set; } public IWeightedAverageAggregation WeightedAverage { get; set; } public IMedianAbsoluteDeviationAggregation MedianAbsoluteDeviation { get; set; } public IMultiTermsAggregation MultiTerms { get; set; } public IVariableWidthHistogramAggregation VariableWidthHistogram { get; set; } public void Accept(IAggregationVisitor visitor) { if (visitor.Scope == AggregationVisitorScope.Unknown) visitor.Scope = AggregationVisitorScope.Aggregation; new AggregationWalker().Walk(this, visitor); } public static implicit operator AggregationContainer(AggregationBase aggregator) { if (aggregator == null) return null; var container = new AggregationContainer(); aggregator.WrapInContainer(container); var bucket = aggregator as BucketAggregationBase; container.Aggregations = bucket?.Aggregations; var combinator = aggregator as AggregationCombinator; if (combinator?.Aggregations != null) { var dict = new AggregationDictionary(); foreach (var agg in combinator.Aggregations) dict.Add(((IAggregation)agg).Name, agg); container.Aggregations = dict; } container.Meta = aggregator.Meta; return container; } } public class AggregationContainerDescriptor : DescriptorBase, IAggregationContainer>, IAggregationContainer where T : class { IAdjacencyMatrixAggregation IAggregationContainer.AdjacencyMatrix { get; set; } AggregationDictionary IAggregationContainer.Aggregations { get; set; } IAverageAggregation IAggregationContainer.Average { get; set; } IAverageBucketAggregation IAggregationContainer.AverageBucket { get; set; } IBucketScriptAggregation IAggregationContainer.BucketScript { get; set; } IBucketSelectorAggregation IAggregationContainer.BucketSelector { get; set; } IBucketSortAggregation IAggregationContainer.BucketSort { get; set; } ICardinalityAggregation IAggregationContainer.Cardinality { get; set; } IChildrenAggregation IAggregationContainer.Children { get; set; } ICompositeAggregation IAggregationContainer.Composite { get; set; } ICumulativeSumAggregation IAggregationContainer.CumulativeSum { get; set; } IDateHistogramAggregation IAggregationContainer.DateHistogram { get; set; } IAutoDateHistogramAggregation IAggregationContainer.AutoDateHistogram { get; set; } IDateRangeAggregation IAggregationContainer.DateRange { get; set; } IDerivativeAggregation IAggregationContainer.Derivative { get; set; } IDiversifiedSamplerAggregation IAggregationContainer.DiversifiedSampler { get; set; } IExtendedStatsAggregation IAggregationContainer.ExtendedStats { get; set; } IExtendedStatsBucketAggregation IAggregationContainer.ExtendedStatsBucket { get; set; } IFilterAggregation IAggregationContainer.Filter { get; set; } IFiltersAggregation IAggregationContainer.Filters { get; set; } IGeoBoundsAggregation IAggregationContainer.GeoBounds { get; set; } IGeoCentroidAggregation IAggregationContainer.GeoCentroid { get; set; } IGeoDistanceAggregation IAggregationContainer.GeoDistance { get; set; } IGeoHashGridAggregation IAggregationContainer.GeoHash { get; set; } IGeoLineAggregation IAggregationContainer.GeoLine { get; set; } IGeoTileGridAggregation IAggregationContainer.GeoTile { get; set; } IGlobalAggregation IAggregationContainer.Global { get; set; } IHistogramAggregation IAggregationContainer.Histogram { get; set; } IIpRangeAggregation IAggregationContainer.IpRange { get; set; } IMatrixStatsAggregation IAggregationContainer.MatrixStats { get; set; } IMaxAggregation IAggregationContainer.Max { get; set; } IMaxBucketAggregation IAggregationContainer.MaxBucket { get; set; } IDictionary IAggregationContainer.Meta { get; set; } IMinAggregation IAggregationContainer.Min { get; set; } IMinBucketAggregation IAggregationContainer.MinBucket { get; set; } IMissingAggregation IAggregationContainer.Missing { get; set; } IMovingAverageAggregation IAggregationContainer.MovingAverage { get; set; } IMovingFunctionAggregation IAggregationContainer.MovingFunction { get; set; } IMultiTermsAggregation IAggregationContainer.MultiTerms { get; set; } INestedAggregation IAggregationContainer.Nested { get; set; } IParentAggregation IAggregationContainer.Parent { get; set; } IPercentileRanksAggregation IAggregationContainer.PercentileRanks { get; set; } IPercentilesAggregation IAggregationContainer.Percentiles { get; set; } IPercentilesBucketAggregation IAggregationContainer.PercentilesBucket { get; set; } IRangeAggregation IAggregationContainer.Range { get; set; } IRareTermsAggregation IAggregationContainer.RareTerms { get; set; } IReverseNestedAggregation IAggregationContainer.ReverseNested { get; set; } ISamplerAggregation IAggregationContainer.Sampler { get; set; } IScriptedMetricAggregation IAggregationContainer.ScriptedMetric { get; set; } ISerialDifferencingAggregation IAggregationContainer.SerialDifferencing { get; set; } ISignificantTermsAggregation IAggregationContainer.SignificantTerms { get; set; } ISignificantTextAggregation IAggregationContainer.SignificantText { get; set; } IStatsAggregation IAggregationContainer.Stats { get; set; } IStatsBucketAggregation IAggregationContainer.StatsBucket { get; set; } ISumAggregation IAggregationContainer.Sum { get; set; } ISumBucketAggregation IAggregationContainer.SumBucket { get; set; } ITermsAggregation IAggregationContainer.Terms { get; set; } ITopHitsAggregation IAggregationContainer.TopHits { get; set; } IValueCountAggregation IAggregationContainer.ValueCount { get; set; } IWeightedAverageAggregation IAggregationContainer.WeightedAverage { get; set; } IMedianAbsoluteDeviationAggregation IAggregationContainer.MedianAbsoluteDeviation { get; set; } IVariableWidthHistogramAggregation IAggregationContainer.VariableWidthHistogram { get; set; } public void Accept(IAggregationVisitor visitor) { if (visitor.Scope == AggregationVisitorScope.Unknown) visitor.Scope = AggregationVisitorScope.Aggregation; new AggregationWalker().Walk(this, visitor); } public AggregationContainerDescriptor Average(string name, Func, IAverageAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Average = d); public AggregationContainerDescriptor DateHistogram(string name, Func, IDateHistogramAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.DateHistogram = d); public AggregationContainerDescriptor AutoDateHistogram(string name, Func, IAutoDateHistogramAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.AutoDateHistogram = d); public AggregationContainerDescriptor Percentiles(string name, Func, IPercentilesAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Percentiles = d); public AggregationContainerDescriptor PercentileRanks(string name, Func, IPercentileRanksAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.PercentileRanks = d); public AggregationContainerDescriptor DateRange(string name, Func, IDateRangeAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.DateRange = d); public AggregationContainerDescriptor ExtendedStats(string name, Func, IExtendedStatsAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.ExtendedStats = d); public AggregationContainerDescriptor Filter(string name, Func, IFilterAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Filter = d); public AggregationContainerDescriptor Filters(string name, Func, IFiltersAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Filters = d); public AggregationContainerDescriptor GeoDistance(string name, Func, IGeoDistanceAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.GeoDistance = d); public AggregationContainerDescriptor GeoHash(string name, Func, IGeoHashGridAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.GeoHash = d); public AggregationContainerDescriptor GeoLine(string name, Func, IGeoLineAggregation> selector) => _SetInnerAggregation(name, selector, (a, d) => a.GeoLine = d); public AggregationContainerDescriptor GeoTile(string name, Func, IGeoTileGridAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.GeoTile = d); public AggregationContainerDescriptor GeoBounds(string name, Func, IGeoBoundsAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.GeoBounds = d); public AggregationContainerDescriptor Histogram(string name, Func, IHistogramAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Histogram = d); public AggregationContainerDescriptor Global(string name, Func, IGlobalAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Global = d); public AggregationContainerDescriptor IpRange(string name, Func, IIpRangeAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.IpRange = d); public AggregationContainerDescriptor Max(string name, Func, IMaxAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Max = d); public AggregationContainerDescriptor Min(string name, Func, IMinAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Min = d); public AggregationContainerDescriptor Cardinality(string name, Func, ICardinalityAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Cardinality = d); public AggregationContainerDescriptor Missing(string name, Func, IMissingAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Missing = d); public AggregationContainerDescriptor MultiTerms(string name, Func, IMultiTermsAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.MultiTerms = d); public AggregationContainerDescriptor Nested(string name, Func, INestedAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Nested = d); /// public AggregationContainerDescriptor Parent(string name, Func, IParentAggregation> selector ) where TParent : class => _SetInnerAggregation(name, selector, (a, d) => a.Parent = d); public AggregationContainerDescriptor ReverseNested(string name, Func, IReverseNestedAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.ReverseNested = d); public AggregationContainerDescriptor Range(string name, Func, IRangeAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Range = d); public AggregationContainerDescriptor RareTerms(string name, Func, IRareTermsAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.RareTerms = d); public AggregationContainerDescriptor Stats(string name, Func, IStatsAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Stats = d); public AggregationContainerDescriptor Sum(string name, Func, ISumAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Sum = d); public AggregationContainerDescriptor Terms(string name, Func, ITermsAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Terms = d); public AggregationContainerDescriptor SignificantTerms(string name, Func, ISignificantTermsAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.SignificantTerms = d); public AggregationContainerDescriptor SignificantText(string name, Func, ISignificantTextAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.SignificantText = d); public AggregationContainerDescriptor ValueCount(string name, Func, IValueCountAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.ValueCount = d); public AggregationContainerDescriptor TopHits(string name, Func, ITopHitsAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.TopHits = d); public AggregationContainerDescriptor Children(string name, Func, IChildrenAggregation> selector ) where TChild : class => _SetInnerAggregation(name, selector, (a, d) => a.Children = d); public AggregationContainerDescriptor ScriptedMetric(string name, Func, IScriptedMetricAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.ScriptedMetric = d); public AggregationContainerDescriptor AverageBucket(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.AverageBucket = d); public AggregationContainerDescriptor Derivative(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Derivative = d); public AggregationContainerDescriptor MaxBucket(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.MaxBucket = d); public AggregationContainerDescriptor MinBucket(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.MinBucket = d); public AggregationContainerDescriptor SumBucket(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.SumBucket = d); public AggregationContainerDescriptor StatsBucket(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.StatsBucket = d); public AggregationContainerDescriptor ExtendedStatsBucket(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.ExtendedStatsBucket = d); public AggregationContainerDescriptor PercentilesBucket(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.PercentilesBucket = d); public AggregationContainerDescriptor MovingAverage(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.MovingAverage = d); public AggregationContainerDescriptor MovingFunction(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.MovingFunction = d); public AggregationContainerDescriptor CumulativeSum(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.CumulativeSum = d); public AggregationContainerDescriptor SerialDifferencing(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.SerialDifferencing = d); public AggregationContainerDescriptor BucketScript(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.BucketScript = d); public AggregationContainerDescriptor BucketSelector(string name, Func selector ) => _SetInnerAggregation(name, selector, (a, d) => a.BucketSelector = d); public AggregationContainerDescriptor BucketSort(string name, Func, IBucketSortAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.BucketSort = d); public AggregationContainerDescriptor Sampler(string name, Func, ISamplerAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Sampler = d); public AggregationContainerDescriptor DiversifiedSampler(string name, Func, IDiversifiedSamplerAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.DiversifiedSampler = d); public AggregationContainerDescriptor GeoCentroid(string name, Func, IGeoCentroidAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.GeoCentroid = d); public AggregationContainerDescriptor MatrixStats(string name, Func, IMatrixStatsAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.MatrixStats = d); public AggregationContainerDescriptor AdjacencyMatrix(string name, Func, IAdjacencyMatrixAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.AdjacencyMatrix = d); public AggregationContainerDescriptor Composite(string name, Func, ICompositeAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.Composite = d); public AggregationContainerDescriptor WeightedAverage(string name, Func, IWeightedAverageAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.WeightedAverage = d); public AggregationContainerDescriptor MedianAbsoluteDeviation(string name, Func, IMedianAbsoluteDeviationAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.MedianAbsoluteDeviation = d); public AggregationContainerDescriptor VariableWidthHistogram(string name, Func, IVariableWidthHistogramAggregation> selector ) => _SetInnerAggregation(name, selector, (a, d) => a.VariableWidthHistogram = d); /// /// Fluent methods do not assign to properties on `this` directly but on IAggregationContainers inside /// `this.Aggregations[string, IContainer] /// private AggregationContainerDescriptor _SetInnerAggregation( string key, Func selector , Action assignToProperty ) where TAggregator : IAggregation, TAggregatorInterface, new() where TAggregatorInterface : IAggregation { var aggregator = selector(new TAggregator()); //create new isolated container for new aggregator and assign to the right property var container = new AggregationContainer { Meta = aggregator.Meta }; assignToProperty(container, aggregator); //create aggregations dictionary on `this` if it does not exist already IAggregationContainer self = this; if (self.Aggregations == null) self.Aggregations = new Dictionary(); //if the aggregator is a bucket aggregator (meaning it contains nested aggregations); if (aggregator is IBucketAggregation bucket && bucket.Aggregations.HasAny()) { //make sure we copy those aggregations to the isolated container's //own .Aggregations container (the one that gets serialized to "aggs") IAggregationContainer d = container; d.Aggregations = bucket.Aggregations; } //assign the aggregations container under Aggregations ("aggs" in the json) self.Aggregations[key] = container; return this; } //always evaluate to false so that each side of && equation is evaluated public static bool operator false(AggregationContainerDescriptor a) => false; //always evaluate to false so that each side of && equation is evaluated public static bool operator true(AggregationContainerDescriptor a) => false; public static AggregationContainerDescriptor operator &(AggregationContainerDescriptor left, AggregationContainerDescriptor right) { if (right == null) return left; if (left == null) return right; if (Equals(left, right)) return left; var d = new AggregationContainerDescriptor(); var leftAggs = (IDictionary)((IAggregationContainer)left).Aggregations; var rightAggs = (IDictionary)((IAggregationContainer)right).Aggregations; foreach (var kv in rightAggs) { if (leftAggs.ContainsKey(kv.Key)) { var message = $"Can not merge two {nameof(AggregationContainerDescriptor)}'s"; message += $" {kv.Key} is defined in both"; throw new Exception(message); } leftAggs.Add(kv.Key, kv.Value); } ((IAggregationContainer)d).Aggregations = ((IAggregationContainer)left).Aggregations; return d; } } }