/* 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 OpenSearch.Net;
using OpenSearch.Net.Utf8Json;
namespace OpenSearch.Client
{
///
/// Contains aggregates that are returned by OpenSearch. In OSC, Aggregation always refers to an aggregation
/// request to OpenSearch and an Aggregate describes an aggregation response.
///
[JsonFormatter(typeof(AggregateDictionaryFormatter))]
public class AggregateDictionary : IsAReadOnlyDictionaryBase
{
internal static readonly char[] TypedKeysSeparator = { '#' };
[SerializationConstructor]
public AggregateDictionary(IReadOnlyDictionary backingDictionary) : base(backingDictionary) { }
public static AggregateDictionary Default { get; } = new AggregateDictionary(EmptyReadOnly.Dictionary);
protected override string Sanitize(string key)
{
//typed_keys = true on results in aggregation keys being returned as "#"
var tokens = TypedKeyTokens(key);
return tokens.Length > 1 ? tokens[1] : tokens[0];
}
internal static string[] TypedKeyTokens(string key)
{
var tokens = key.Split(TypedKeysSeparator, 2, StringSplitOptions.RemoveEmptyEntries);
return tokens;
}
public ValueAggregate Min(string key) => TryGet(key);
public ValueAggregate Max(string key) => TryGet(key);
public ValueAggregate Sum(string key) => TryGet(key);
public ValueAggregate Cardinality(string key) => TryGet(key);
public ValueAggregate Average(string key) => TryGet(key);
public ValueAggregate ValueCount(string key) => TryGet(key);
public ValueAggregate AverageBucket(string key) => TryGet(key);
public ValueAggregate Derivative(string key) => TryGet(key);
public ValueAggregate SumBucket(string key) => TryGet(key);
public ValueAggregate MovingAverage(string key) => TryGet(key);
public ValueAggregate CumulativeSum(string key) => TryGet(key);
public ValueAggregate BucketScript(string key) => TryGet(key);
public ValueAggregate SerialDifferencing(string key) => TryGet(key);
public ValueAggregate WeightedAverage(string key) => TryGet(key);
public KeyedValueAggregate MaxBucket(string key) => TryGet(key);
public KeyedValueAggregate MinBucket(string key) => TryGet(key);
public ScriptedMetricAggregate ScriptedMetric(string key)
{
var valueMetric = TryGet(key);
return valueMetric != null
? new ScriptedMetricAggregate(valueMetric.Value) { Meta = valueMetric.Meta }
: TryGet(key);
}
public StatsAggregate Stats(string key) => TryGet(key);
public StatsAggregate StatsBucket(string key) => TryGet(key);
public ExtendedStatsAggregate ExtendedStats(string key) => TryGet(key);
public ExtendedStatsAggregate ExtendedStatsBucket(string key) => TryGet(key);
public GeoBoundsAggregate GeoBounds(string key) => TryGet(key);
public GeoLineAggregate GeoLine(string key) => TryGet(key);
public PercentilesAggregate Percentiles(string key) => TryGet(key);
public PercentilesAggregate PercentilesBucket(string key) => TryGet(key);
public PercentilesAggregate PercentileRanks(string key) => TryGet(key);
public TopHitsAggregate TopHits(string key) => TryGet(key);
public FiltersAggregate Filters(string key)
{
var named = TryGet(key);
if (named != null)
return named;
var anonymous = TryGet(key);
return anonymous != null
? new FiltersAggregate { Buckets = anonymous.Items.OfType().ToList(), Meta = anonymous.Meta }
: null;
}
public SingleBucketAggregate Global(string key) => TryGet(key);
public SingleBucketAggregate Filter(string key) => TryGet(key);
public SingleBucketAggregate Missing(string key) => TryGet(key);
public SingleBucketAggregate Nested(string key) => TryGet(key);
public ValueAggregate Normalize(string key) => TryGet(key);
public SingleBucketAggregate ReverseNested(string key) => TryGet(key);
public SingleBucketAggregate Children(string key) => TryGet(key);
public SingleBucketAggregate Parent(string key) => TryGet(key);
public SingleBucketAggregate Sampler(string key) => TryGet(key);
public SingleBucketAggregate DiversifiedSampler(string key) => TryGet(key);
public GeoCentroidAggregate GeoCentroid(string key) => TryGet(key);
public SignificantTermsAggregate SignificantTerms(string key)
{
var bucket = TryGet(key);
return bucket == null
? null
: new SignificantTermsAggregate
{
BgCount = bucket.BgCount,
DocCount = bucket.DocCount,
Buckets = GetSignificantTermsBuckets(bucket.Items).ToList(),
Meta = bucket.Meta
};
}
public SignificantTermsAggregate SignificantTerms(string key) => SignificantTerms(key);
public SignificantTermsAggregate SignificantText(string key)
{
var bucket = TryGet(key);
return bucket == null
? null
: new SignificantTermsAggregate
{
BgCount = bucket.BgCount,
DocCount = bucket.DocCount,
Buckets = GetSignificantTermsBuckets(bucket.Items).ToList(),
Meta = bucket.Meta
};
}
public SignificantTermsAggregate SignificantText(string key) => SignificantText(key);
public TermsAggregate Terms(string key)
{
var bucket = TryGet(key);
return bucket == null
? null
: new TermsAggregate
{
DocCountErrorUpperBound = bucket.DocCountErrorUpperBound,
SumOtherDocCount = bucket.SumOtherDocCount,
Buckets = GetKeyedBuckets(bucket.Items).ToList(),
Meta = bucket.Meta
};
}
public TermsAggregate Terms(string key) => Terms(key);
public MultiBucketAggregate> Histogram(string key) => GetMultiKeyedBucketAggregate(key);
public MultiBucketAggregate> GeoHash(string key) => GetMultiKeyedBucketAggregate(key);
public MultiBucketAggregate> GeoTile(string key) => GetMultiKeyedBucketAggregate(key);
public MultiBucketAggregate> AdjacencyMatrix(string key) => GetMultiKeyedBucketAggregate(key);
public MultiBucketAggregate> RareTerms(string key)
{
var bucket = TryGet(key);
return bucket == null
? null
: new MultiBucketAggregate>
{
Buckets = GetRareTermsBuckets(bucket.Items).ToList(),
Meta = bucket.Meta
};
}
public MultiBucketAggregate> RareTerms(string key) => RareTerms(key);
public MultiBucketAggregate Range(string key) => GetMultiBucketAggregate(key);
public MultiBucketAggregate DateRange(string key) => GetMultiBucketAggregate(key);
public MultiBucketAggregate IpRange(string key) => GetMultiBucketAggregate(key);
public MultiBucketAggregate GeoDistance(string key) => GetMultiBucketAggregate(key);
public MultiBucketAggregate DateHistogram(string key) => GetMultiBucketAggregate(key);
public MultiBucketAggregate VariableWidthHistogram(string key) => GetMultiBucketAggregate(key);
public MultiTermsAggregate MultiTerms(string key) => MultiTerms(key);
public MultiTermsAggregate MultiTerms(string key)
{
var bucket = TryGet(key);
return bucket == null
? null
: new MultiTermsAggregate
{
DocCountErrorUpperBound = bucket.DocCountErrorUpperBound,
SumOtherDocCount = bucket.SumOtherDocCount,
Buckets = GetMultiTermsBuckets(bucket.Items).ToList(),
Meta = bucket.Meta
};
}
public AutoDateHistogramAggregate AutoDateHistogram(string key)
{
var bucket = TryGet(key);
if (bucket == null) return null;
return new AutoDateHistogramAggregate
{
Buckets = bucket.Items.OfType().ToList(),
Meta = bucket.Meta,
AutoInterval = bucket.AutoInterval
};
}
public CompositeBucketAggregate Composite(string key)
{
var bucket = TryGet(key);
if (bucket == null) return null;
return new CompositeBucketAggregate
{
Buckets = bucket.Items.OfType().ToList(),
Meta = bucket.Meta,
AfterKey = bucket.AfterKey
};
}
public MatrixStatsAggregate MatrixStats(string key) => TryGet(key);
public ValueAggregate MedianAbsoluteDeviation(string key) => TryGet(key);
private TAggregate TryGet(string key) where TAggregate : class, IAggregate =>
BackingDictionary.TryGetValue(key, out var agg) ? agg as TAggregate : null;
private MultiBucketAggregate GetMultiBucketAggregate(string key)
where TBucket : IBucket
{
var bucket = TryGet(key);
if (bucket == null) return null;
return new MultiBucketAggregate
{
Buckets = bucket.Items.OfType().ToList(),
Meta = bucket.Meta
};
}
private MultiBucketAggregate> GetMultiKeyedBucketAggregate(string key)
{
var bucket = TryGet(key);
if (bucket == null) return null;
return new MultiBucketAggregate>
{
Buckets = GetKeyedBuckets(bucket.Items).ToList(),
Meta = bucket.Meta
};
}
private IEnumerable> GetKeyedBuckets(IEnumerable items)
{
var buckets = items.Cast>();
foreach (var bucket in buckets)
yield return new KeyedBucket(bucket.BackingDictionary)
{
Key = GetKeyFromBucketKey(bucket.Key),
KeyAsString = bucket.KeyAsString,
DocCount = bucket.DocCount,
DocCountErrorUpperBound = bucket.DocCountErrorUpperBound
};
}
private IEnumerable> GetSignificantTermsBuckets(IEnumerable items)
{
var buckets = items.Cast>();
foreach (var bucket in buckets)
yield return new SignificantTermsBucket(bucket.BackingDictionary)
{
Key = GetKeyFromBucketKey(bucket.Key),
BgCount = bucket.BgCount,
DocCount = bucket.DocCount,
Score = bucket.Score
};
}
private IEnumerable> GetRareTermsBuckets(IEnumerable items)
{
var buckets = items.Cast>();
foreach (var bucket in buckets)
yield return new RareTermsBucket(bucket.BackingDictionary)
{
Key = GetKeyFromBucketKey(bucket.Key),
DocCount = bucket.DocCount.GetValueOrDefault(0)
};
}
private static IEnumerable> GetMultiTermsBuckets(IEnumerable items)
{
var buckets = items.Cast>();
foreach (var bucket in buckets)
{
var aggregates = new MultiTermsBucket(bucket.BackingDictionary)
{
DocCount = bucket.DocCount,
DocCountErrorUpperBound = bucket.DocCountErrorUpperBound,
KeyAsString = bucket.KeyAsString
};
if (bucket.Key is List