From 36408395931c9bad8c3e26fb563eb567d4d2f0ba Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Mon, 24 Sep 2018 17:36:29 +0200 Subject: [PATCH 1/4] Add support for weighted average aggregation --- src/Nest/Aggregations/AggregateDictionary.cs | 2 + src/Nest/Aggregations/AggregationContainer.cs | 11 +++ .../Aggregations/Metric/MetricAggregation.cs | 5 +- .../WeightedAverageAggregation.cs | 78 +++++++++++++++++++ .../WeightedAverage/WeightedAverageValue.cs | 51 ++++++++++++ .../WeightedAverageAggregationUsageTests.cs | 65 ++++++++++++++++ 6 files changed, 208 insertions(+), 4 deletions(-) create mode 100644 src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageAggregation.cs create mode 100644 src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageValue.cs create mode 100644 src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs diff --git a/src/Nest/Aggregations/AggregateDictionary.cs b/src/Nest/Aggregations/AggregateDictionary.cs index c59b27d8abf..94fcf5ab8c6 100644 --- a/src/Nest/Aggregations/AggregateDictionary.cs +++ b/src/Nest/Aggregations/AggregateDictionary.cs @@ -56,6 +56,8 @@ internal static string[] TypedKeyTokens(string key) public ValueAggregate SerialDifferencing(string key) => this.TryGet(key); + public ValueAggregate WeightedAverage(string key) => this.TryGet(key); + public KeyedValueAggregate MaxBucket(string key) => this.TryGet(key); public KeyedValueAggregate MinBucket(string key) => this.TryGet(key); diff --git a/src/Nest/Aggregations/AggregationContainer.cs b/src/Nest/Aggregations/AggregationContainer.cs index 83e9f931c2f..402ee64018c 100644 --- a/src/Nest/Aggregations/AggregationContainer.cs +++ b/src/Nest/Aggregations/AggregationContainer.cs @@ -215,6 +215,9 @@ public interface IAggregationContainer [JsonProperty("composite")] ICompositeAggregation Composite { get; set; } + [JsonProperty("weighted_avg")] + IWeightedAverageAggregation WeightedAverage { get; set; } + [JsonProperty("aggs")] AggregationDictionary Aggregations { get; set; } @@ -315,6 +318,8 @@ public class AggregationContainer : IAggregationContainer public ICompositeAggregation Composite { get; set; } + public IWeightedAverageAggregation WeightedAverage { get; set; } + public AggregationDictionary Aggregations { get; set; } public static implicit operator AggregationContainer(AggregationBase aggregator) @@ -450,6 +455,8 @@ public class AggregationContainerDescriptor : DescriptorBase Average(string name, Func, IAverageAggregation> selector) => _SetInnerAggregation(name, selector, (a, d) => a.Average = d); @@ -646,6 +653,10 @@ 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); + /// /// Fluent methods do not assign to properties on `this` directly but on IAggregationContainers inside `this.Aggregations[string, IContainer] /// diff --git a/src/Nest/Aggregations/Metric/MetricAggregation.cs b/src/Nest/Aggregations/Metric/MetricAggregation.cs index accd30227c3..eb429e81b02 100644 --- a/src/Nest/Aggregations/Metric/MetricAggregation.cs +++ b/src/Nest/Aggregations/Metric/MetricAggregation.cs @@ -21,10 +21,7 @@ public abstract class MetricAggregationBase : AggregationBase, IMetricAggregatio { internal MetricAggregationBase() { } - protected MetricAggregationBase(string name, Field field) : base(name) - { - this.Field = field; - } + protected MetricAggregationBase(string name, Field field) : base(name) => this.Field = field; public Field Field { get; set; } public virtual IScript Script { get; set; } diff --git a/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageAggregation.cs b/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageAggregation.cs new file mode 100644 index 00000000000..84f71825523 --- /dev/null +++ b/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageAggregation.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using Newtonsoft.Json; + +namespace Nest +{ + [JsonObject(MemberSerialization = MemberSerialization.OptIn)] + [ContractJsonConverter(typeof(AggregationJsonConverter))] + public interface IWeightedAverageAggregation : IAggregation + { + /// The configuration for the field or script that provides the values + [JsonProperty("value")] + IWeightedAverageValue Value { get; set; } + /// The configuration for the field or script that provides the weights /// + [JsonProperty("weight")] + IWeightedAverageValue Weight { get; set; } + /// The optional numeric response formatter + [JsonProperty("format")] + string Format { get; set; } + /// A hint about the values for pure scripts or unmapped fields + [JsonProperty("value_type")] + // TODO map as on server enum ? + // https://github.com/elastic/elasticsearch/blob/master/server/src/main/java/org/elasticsearch/search/aggregations/support/ValueType.java + string ValueType { get; set; } + } + + public class WeightedAverageAggregation : AggregationBase, IWeightedAverageAggregation + { + internal WeightedAverageAggregation() { } + public WeightedAverageAggregation(string name) : base(name) { } + + internal override void WrapInContainer(AggregationContainer c) => c.WeightedAverage = this; + + /// > + public IWeightedAverageValue Value { get; set; } + /// > + public IWeightedAverageValue Weight { get; set; } + /// > + public string Format { get; set; } + /// > + public string ValueType { get; set; } + } + + public class WeightedAverageAggregationDescriptor + : DescriptorBase, IWeightedAverageAggregation> + , IWeightedAverageAggregation + where T : class + { + IWeightedAverageValue IWeightedAverageAggregation.Value { get; set; } + IWeightedAverageValue IWeightedAverageAggregation.Weight { get; set; } + string IWeightedAverageAggregation.Format { get; set; } + string IWeightedAverageAggregation.ValueType { get; set; } + + string IAggregation.Name { get; set; } + IDictionary IAggregation.Meta { get; set; } + /// > + public WeightedAverageAggregationDescriptor Meta(Func, FluentDictionary> selector) => + Assign(a => a.Meta = selector?.Invoke(new FluentDictionary())); + + /// > + public WeightedAverageAggregationDescriptor Value(Func, IWeightedAverageValue> selector) => + Assign(a => a.Value = selector?.Invoke(new WeightedAverageValueDescriptor())); + + /// > + public WeightedAverageAggregationDescriptor Weight(Func, IWeightedAverageValue> selector) => + Assign(a => a.Weight = selector?.Invoke(new WeightedAverageValueDescriptor())); + + /// > + public WeightedAverageAggregationDescriptor Format(string format) => Assign(a => a.Format = format); + + /// > + public WeightedAverageAggregationDescriptor ValueType(string valueType) => Assign(a => a.ValueType = valueType); + + + } + +} diff --git a/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageValue.cs b/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageValue.cs new file mode 100644 index 00000000000..7810c6228cf --- /dev/null +++ b/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageValue.cs @@ -0,0 +1,51 @@ +using System; +using System.Linq.Expressions; +using Newtonsoft.Json; + +namespace Nest +{ + [JsonObject(MemberSerialization = MemberSerialization.OptIn)] + [ContractJsonConverter(typeof(ReadAsTypeJsonConverter))] + public interface IWeightedAverageValue + { + [JsonProperty("field")] + Field Field { get; set; } + + [JsonProperty("script")] + IScript Script { get; set; } + + [JsonProperty("missing")] + double? Missing { get; set; } + } + + public class WeightedAverageValue : IWeightedAverageValue + { + public WeightedAverageValue(Field field) => this.Field = field; + public WeightedAverageValue(IScript script) => this.Script = script; + + public Field Field { get; set; } + public virtual IScript Script { get; set; } + public double? Missing { get; set; } + } + + public class WeightedAverageValueDescriptor : DescriptorBase, IWeightedAverageValue> + , IWeightedAverageValue + where T : class + { + Field IWeightedAverageValue.Field { get; set; } + IScript IWeightedAverageValue.Script { get; set; } + double? IWeightedAverageValue.Missing { get; set; } + + public WeightedAverageValueDescriptor Field(Field field) => Assign(a => a.Field = field); + + public WeightedAverageValueDescriptor Field(Expression> field) => Assign(a => a.Field = field); + + public virtual WeightedAverageValueDescriptor Script(string script) => Assign(a => a.Script = (InlineScript)script); + + public virtual WeightedAverageValueDescriptor Script(Func scriptSelector) => + Assign(a => a.Script = scriptSelector?.Invoke(new ScriptDescriptor())); + + public WeightedAverageValueDescriptor Missing(double? missing) => Assign(a => a.Missing = missing); + } + +} diff --git a/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs b/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs new file mode 100644 index 00000000000..e8dc1e179a3 --- /dev/null +++ b/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs @@ -0,0 +1,65 @@ +using System; +using FluentAssertions; +using Nest; +using Tests.Framework.Integration; +using static Nest.Infer; +using Tests.Core.Extensions; +using Tests.Core.ManagedElasticsearch.Clusters; +using Tests.Domain; + +namespace Tests.Aggregations.Metric.WeightedAverage +{ + public class WeightedAverageAggregationUsageTests : AggregationUsageTestBase + { + public WeightedAverageAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } + + private const string AggregationName = "weighted_avg_commits"; + + protected override object AggregationJson => new + { + aggs = new + { + weighted_avg_commits = new + { + weighted_avg = new + { + value = new + { + field = "numberOfCommits", + missing = 0.0 + }, + weight = new + { + field = "numberOfContributors" + } + } + } + }, + size = 0 + }; + + protected override Func, IAggregationContainer> FluentAggs => a => a + .WeightedAverage(AggregationName, avg => avg + .Value(v => v.Field(p => p.NumberOfCommits).Missing(0)) + .Weight(v => v.Field(p => p.NumberOfContributors)) + ); + + protected override AggregationDictionary InitializerAggs => + new WeightedAverageAggregation(AggregationName) + { + Value = new WeightedAverageValue(Field(p => p.NumberOfCommits)) + { + Missing = 0 + }, + Weight = new WeightedAverageValue(Field(p => p.NumberOfCommits)) + }; + + protected override void ExpectResponse(ISearchResponse response) + { + response.ShouldBeValid(); + var commitsAvg = response.Aggregations.WeightedAverage(AggregationName); + commitsAvg.Should().NotBeNull(); + commitsAvg.Value.Should().BeGreaterThan(0); + } + } +} From 032ad8fef70f17ece0246764c62a5988b9e38769 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Mon, 24 Sep 2018 18:02:49 +0200 Subject: [PATCH 2/4] fix failing json serialization tests --- .../WeightedAverage/WeightedAverageValue.cs | 3 ++- .../WeightedAverageAggregationUsageTests.cs | 26 ++++++++----------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageValue.cs b/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageValue.cs index 7810c6228cf..5f8dfd2f75d 100644 --- a/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageValue.cs +++ b/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageValue.cs @@ -5,7 +5,7 @@ namespace Nest { [JsonObject(MemberSerialization = MemberSerialization.OptIn)] - [ContractJsonConverter(typeof(ReadAsTypeJsonConverter))] + [ContractJsonConverter(typeof(ReadAsTypeJsonConverter))] public interface IWeightedAverageValue { [JsonProperty("field")] @@ -20,6 +20,7 @@ public interface IWeightedAverageValue public class WeightedAverageValue : IWeightedAverageValue { + internal WeightedAverageValue() { } public WeightedAverageValue(Field field) => this.Field = field; public WeightedAverageValue(IScript script) => this.Script = script; diff --git a/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs b/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs index e8dc1e179a3..d4c2cca1522 100644 --- a/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs +++ b/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs @@ -17,25 +17,21 @@ public WeightedAverageAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usa protected override object AggregationJson => new { - aggs = new + weighted_avg_commits = new { - weighted_avg_commits = new + weighted_avg = new { - weighted_avg = new + value = new { - value = new - { - field = "numberOfCommits", - missing = 0.0 - }, - weight = new - { - field = "numberOfContributors" - } + field = "numberOfCommits", + missing = 0.0 + }, + weight = new + { + field = "numberOfContributors" } } - }, - size = 0 + } }; protected override Func, IAggregationContainer> FluentAggs => a => a @@ -51,7 +47,7 @@ public WeightedAverageAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usa { Missing = 0 }, - Weight = new WeightedAverageValue(Field(p => p.NumberOfCommits)) + Weight = new WeightedAverageValue(Field(p => p.NumberOfContributors)) }; protected override void ExpectResponse(ISearchResponse response) From 3d0e6c08de9a620b447a69b48e1ba1513d634919 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Wed, 17 Oct 2018 09:19:26 +1000 Subject: [PATCH 3/4] Implement ValueType as an enum --- src/Nest/Aggregations/Aggregation.cs | 35 ++++++++--- .../WeightedAverageAggregation.cs | 39 ++++++------- .../WeightedAverage/WeightedAverageValue.cs | 58 ++++++++++++++++++- .../WeightedAverageAggregationUsageTests.cs | 29 +++++++--- 4 files changed, 119 insertions(+), 42 deletions(-) diff --git a/src/Nest/Aggregations/Aggregation.cs b/src/Nest/Aggregations/Aggregation.cs index 9faa0506a03..a718e82731d 100644 --- a/src/Nest/Aggregations/Aggregation.cs +++ b/src/Nest/Aggregations/Aggregation.cs @@ -1,5 +1,6 @@ using Newtonsoft.Json; using System.Collections.Generic; +using System.Linq; namespace Nest { @@ -9,14 +10,25 @@ namespace Nest [JsonObject(MemberSerialization = MemberSerialization.OptIn)] public interface IAggregation { + /// + /// name of the aggregation + /// string Name { get; set; } + + /// + /// metadata to associate with the individual aggregation at request time that + /// will be returned in place at response time + /// IDictionary Meta { get; set; } } + /// public abstract class AggregationBase : IAggregation { + /// string IAggregation.Name { get; set; } + /// public IDictionary Meta { get; set; } internal AggregationBase() { } @@ -34,12 +46,13 @@ protected AggregationBase(string name) //always evaluate to false so that each side of && equation is evaluated public static bool operator true(AggregationBase a) => false; - public static AggregationBase operator &(AggregationBase left, AggregationBase right) - { - return new AggregationCombinator(null, left, right); - } + public static AggregationBase operator &(AggregationBase left, AggregationBase right) => + new AggregationCombinator(null, left, right); } + /// + /// Combines aggregations into a single list of aggregations + /// internal class AggregationCombinator : AggregationBase, IAggregation { internal List Aggregations { get; } = new List(); @@ -54,13 +67,17 @@ public AggregationCombinator(string name, AggregationBase left, AggregationBase private void AddAggregation(AggregationBase agg) { - if (agg == null) return; - var combinator = agg as AggregationCombinator; - if ((combinator?.Aggregations.HasAny()).GetValueOrDefault(false)) + switch (agg) { - this.Aggregations.AddRange(combinator.Aggregations); + case null: + return; + case AggregationCombinator combinator when combinator.Aggregations.Any(): + this.Aggregations.AddRange(combinator.Aggregations); + break; + default: + this.Aggregations.Add(agg); + break; } - else this.Aggregations.Add(agg); } } } diff --git a/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageAggregation.cs b/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageAggregation.cs index 84f71825523..678fd785b31 100644 --- a/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageAggregation.cs +++ b/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageAggregation.cs @@ -9,20 +9,18 @@ namespace Nest [ContractJsonConverter(typeof(AggregationJsonConverter))] public interface IWeightedAverageAggregation : IAggregation { - /// The configuration for the field or script that provides the values + /// The configuration for the field or script that provides the values [JsonProperty("value")] IWeightedAverageValue Value { get; set; } - /// The configuration for the field or script that provides the weights /// + /// The configuration for the field or script that provides the weights [JsonProperty("weight")] IWeightedAverageValue Weight { get; set; } - /// The optional numeric response formatter + /// The optional numeric response formatter [JsonProperty("format")] string Format { get; set; } /// A hint about the values for pure scripts or unmapped fields [JsonProperty("value_type")] - // TODO map as on server enum ? - // https://github.com/elastic/elasticsearch/blob/master/server/src/main/java/org/elasticsearch/search/aggregations/support/ValueType.java - string ValueType { get; set; } + ValueType? ValueType { get; set; } } public class WeightedAverageAggregation : AggregationBase, IWeightedAverageAggregation @@ -32,14 +30,14 @@ public WeightedAverageAggregation(string name) : base(name) { } internal override void WrapInContainer(AggregationContainer c) => c.WeightedAverage = this; - /// > + /// public IWeightedAverageValue Value { get; set; } - /// > + /// public IWeightedAverageValue Weight { get; set; } - /// > + /// public string Format { get; set; } - /// > - public string ValueType { get; set; } + /// + public ValueType? ValueType { get; set; } } public class WeightedAverageAggregationDescriptor @@ -50,29 +48,26 @@ public class WeightedAverageAggregationDescriptor IWeightedAverageValue IWeightedAverageAggregation.Value { get; set; } IWeightedAverageValue IWeightedAverageAggregation.Weight { get; set; } string IWeightedAverageAggregation.Format { get; set; } - string IWeightedAverageAggregation.ValueType { get; set; } - + ValueType? IWeightedAverageAggregation.ValueType { get; set; } string IAggregation.Name { get; set; } IDictionary IAggregation.Meta { get; set; } - /// > + + /// public WeightedAverageAggregationDescriptor Meta(Func, FluentDictionary> selector) => Assign(a => a.Meta = selector?.Invoke(new FluentDictionary())); - /// > + /// public WeightedAverageAggregationDescriptor Value(Func, IWeightedAverageValue> selector) => Assign(a => a.Value = selector?.Invoke(new WeightedAverageValueDescriptor())); - /// > + /// public WeightedAverageAggregationDescriptor Weight(Func, IWeightedAverageValue> selector) => Assign(a => a.Weight = selector?.Invoke(new WeightedAverageValueDescriptor())); - /// > + /// public WeightedAverageAggregationDescriptor Format(string format) => Assign(a => a.Format = format); - /// > - public WeightedAverageAggregationDescriptor ValueType(string valueType) => Assign(a => a.ValueType = valueType); - - + /// + public WeightedAverageAggregationDescriptor ValueType(ValueType? valueType) => Assign(a => a.ValueType = valueType); } - } diff --git a/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageValue.cs b/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageValue.cs index 5f8dfd2f75d..8c83af09915 100644 --- a/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageValue.cs +++ b/src/Nest/Aggregations/Metric/WeightedAverage/WeightedAverageValue.cs @@ -1,34 +1,58 @@ using System; using System.Linq.Expressions; +using System.Runtime.Serialization; using Newtonsoft.Json; +using Newtonsoft.Json.Converters; namespace Nest { + /// + /// The configuration for a field or scrip that provides a value or weight + /// for + /// [JsonObject(MemberSerialization = MemberSerialization.OptIn)] [ContractJsonConverter(typeof(ReadAsTypeJsonConverter))] public interface IWeightedAverageValue { + /// + /// The field that values should be extracted from + /// [JsonProperty("field")] Field Field { get; set; } + /// + /// A script to derive the value and the weight from + /// [JsonProperty("script")] IScript Script { get; set; } + /// + /// defines how documents that are missing a value should be treated. + /// The default behavior is different for value and weight: + /// By default, if the value field is missing the document is ignored and the aggregation + /// moves on to the next document. + /// If the weight field is missing, it is assumed to have a weight of 1 (like a normal average). + /// [JsonProperty("missing")] double? Missing { get; set; } } + /// public class WeightedAverageValue : IWeightedAverageValue { internal WeightedAverageValue() { } public WeightedAverageValue(Field field) => this.Field = field; public WeightedAverageValue(IScript script) => this.Script = script; + /// public Field Field { get; set; } - public virtual IScript Script { get; set; } + /// + public IScript Script { get; set; } + /// public double? Missing { get; set; } } + /// public class WeightedAverageValueDescriptor : DescriptorBase, IWeightedAverageValue> , IWeightedAverageValue where T : class @@ -37,16 +61,46 @@ public class WeightedAverageValueDescriptor : DescriptorBase public WeightedAverageValueDescriptor Field(Field field) => Assign(a => a.Field = field); + /// public WeightedAverageValueDescriptor Field(Expression> field) => Assign(a => a.Field = field); - public virtual WeightedAverageValueDescriptor Script(string script) => Assign(a => a.Script = (InlineScript)script); + /// + public virtual WeightedAverageValueDescriptor Script(string script) => Assign(a => a.Script = new InlineScript(script)); + /// public virtual WeightedAverageValueDescriptor Script(Func scriptSelector) => Assign(a => a.Script = scriptSelector?.Invoke(new ScriptDescriptor())); + /// public WeightedAverageValueDescriptor Missing(double? missing) => Assign(a => a.Missing = missing); } + /// + /// The type of value + /// + [JsonConverter(typeof(StringEnumConverter))] + public enum ValueType + { + /// A string value + [EnumMember(Value = "string")] String, + /// A long value that can be used to represent byte, short, integer and long + [EnumMember(Value = "long")] Long, + /// A double value that can be used to represent float and double + [EnumMember(Value = "double")] Double, + /// A number value + [EnumMember(Value = "number")] Number, + /// A date value + [EnumMember(Value = "date")] Date, + /// An IP value + [EnumMember(Value = "ip")] Ip, + /// A numeric value + [EnumMember(Value = "numeric")] Numeric, + /// A geo_point value + [EnumMember(Value = "geo_point")] GeoPoint, + /// A boolean value + [EnumMember(Value = "boolean")] Boolean, + } } diff --git a/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs b/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs index d4c2cca1522..d4a382a87bf 100644 --- a/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs +++ b/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs @@ -6,15 +6,23 @@ using Tests.Core.Extensions; using Tests.Core.ManagedElasticsearch.Clusters; using Tests.Domain; +using ValueType = Nest.ValueType; namespace Tests.Aggregations.Metric.WeightedAverage { + /** + * A single-value metrics aggregation that computes the weighted average of numeric values that are extracted + * from the aggregated documents. These values can be extracted either from specific numeric fields in the documents. + * When calculating a regular average, each datapoint has an equal "weight" i.e. it contributes equally to the final + * value. Weighted averages, on the other hand, weight each datapoint differently. The amount that each + * datapoint contributes to the final value is extracted from the document, or provided by a script. + * + * Be sure to read the Elasticsearch documentation on {ref_current}/search-aggregations-metrics-weight-avg-aggregation.html[Weighted Avg Aggregation] + */ public class WeightedAverageAggregationUsageTests : AggregationUsageTestBase { public WeightedAverageAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } - private const string AggregationName = "weighted_avg_commits"; - protected override object AggregationJson => new { weighted_avg_commits = new @@ -28,32 +36,35 @@ public WeightedAverageAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usa }, weight = new { - field = "numberOfContributors" - } + script = "doc.numberOfContributors.value + 1" + }, + value_type = "long" } } }; protected override Func, IAggregationContainer> FluentAggs => a => a - .WeightedAverage(AggregationName, avg => avg + .WeightedAverage("weighted_avg_commits", avg => avg .Value(v => v.Field(p => p.NumberOfCommits).Missing(0)) - .Weight(v => v.Field(p => p.NumberOfContributors)) + .Weight(w => w.Script("doc.numberOfContributors.value + 1")) + .ValueType(ValueType.Long) ); protected override AggregationDictionary InitializerAggs => - new WeightedAverageAggregation(AggregationName) + new WeightedAverageAggregation("weighted_avg_commits") { Value = new WeightedAverageValue(Field(p => p.NumberOfCommits)) { Missing = 0 }, - Weight = new WeightedAverageValue(Field(p => p.NumberOfContributors)) + Weight = new WeightedAverageValue(new InlineScript("doc.numberOfContributors.value + 1")), + ValueType = ValueType.Long }; protected override void ExpectResponse(ISearchResponse response) { response.ShouldBeValid(); - var commitsAvg = response.Aggregations.WeightedAverage(AggregationName); + var commitsAvg = response.Aggregations.WeightedAverage("weighted_avg_commits"); commitsAvg.Should().NotBeNull(); commitsAvg.Value.Should().BeGreaterThan(0); } From 34a82bc8cf04bf2371d1e4002320ad98e1034095 Mon Sep 17 00:00:00 2001 From: Russ Cam Date: Wed, 17 Oct 2018 12:09:13 +1000 Subject: [PATCH 4/4] Update script structure to match serialized InlineScript --- .../WeightedAverage/WeightedAverageAggregationUsageTests.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs b/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs index d4a382a87bf..9cee7caa097 100644 --- a/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs +++ b/src/Tests/Tests/Aggregations/Metric/WeightedAverage/WeightedAverageAggregationUsageTests.cs @@ -36,7 +36,10 @@ public WeightedAverageAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usa }, weight = new { - script = "doc.numberOfContributors.value + 1" + script = new + { + source = "doc.numberOfContributors.value + 1" + } }, value_type = "long" }