Skip to content

Commit 240ef0c

Browse files
committed
Add support for moving function aggregate elastic/elasticsearch#29594
1 parent f9637a8 commit 240ef0c

File tree

5 files changed

+152
-5
lines changed

5 files changed

+152
-5
lines changed

src/Nest/Aggregations/AggregationContainer.cs

+12
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ public interface IAggregationContainer
185185
[JsonProperty("moving_avg")]
186186
IMovingAverageAggregation MovingAverage { get; set; }
187187

188+
[JsonProperty("moving_fn")]
189+
IMovingFunctionAggregation MovingFunction { get; set; }
190+
188191
[JsonProperty("cumulative_sum")]
189192
ICumulativeSumAggregation CumulativeSum { get; set; }
190193

@@ -295,6 +298,8 @@ public class AggregationContainer : IAggregationContainer
295298

296299
public IMovingAverageAggregation MovingAverage { get; set; }
297300

301+
public IMovingFunctionAggregation MovingFunction { get; set; }
302+
298303
public ICumulativeSumAggregation CumulativeSum { get; set; }
299304

300305
public ISerialDifferencingAggregation SerialDifferencing { get; set; }
@@ -430,6 +435,8 @@ public class AggregationContainerDescriptor<T> : DescriptorBase<AggregationConta
430435

431436
IMovingAverageAggregation IAggregationContainer.MovingAverage { get; set; }
432437

438+
IMovingFunctionAggregation IAggregationContainer.MovingFunction { get; set; }
439+
433440
ICumulativeSumAggregation IAggregationContainer.CumulativeSum { get; set; }
434441

435442
ISerialDifferencingAggregation IAggregationContainer.SerialDifferencing { get; set; }
@@ -606,6 +613,10 @@ public AggregationContainerDescriptor<T> MovingAverage(string name,
606613
Func<MovingAverageAggregationDescriptor, IMovingAverageAggregation> selector) =>
607614
_SetInnerAggregation(name, selector, (a, d) => a.MovingAverage = d);
608615

616+
public AggregationContainerDescriptor<T> MovingFunction(string name,
617+
Func<MovingFunctionAggregationDescriptor, IMovingFunctionAggregation> selector) =>
618+
_SetInnerAggregation(name, selector, (a, d) => a.MovingFunction = d);
619+
609620
public AggregationContainerDescriptor<T> CumulativeSum(string name,
610621
Func<CumulativeSumAggregationDescriptor, ICumulativeSumAggregation> selector) =>
611622
_SetInnerAggregation(name, selector, (a, d) => a.CumulativeSum = d);
@@ -715,5 +726,6 @@ public void Accept(IAggregationVisitor visitor)
715726
((IAggregationContainer)d).Aggregations = ((IAggregationContainer)left).Aggregations;
716727
return d;
717728
}
729+
718730
}
719731
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Newtonsoft.Json;
2+
3+
namespace Nest
4+
{
5+
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
6+
[ContractJsonConverter(typeof(AggregationJsonConverter<MovingFunctionAggregation>))]
7+
public interface IMovingFunctionAggregation : IPipelineAggregation
8+
{
9+
[JsonProperty("window")]
10+
int? Window { get; set; }
11+
12+
[JsonProperty("script")]
13+
string Script { get; set; }
14+
}
15+
16+
public class MovingFunctionAggregation
17+
: PipelineAggregationBase, IMovingFunctionAggregation
18+
{
19+
internal MovingFunctionAggregation () { }
20+
21+
public MovingFunctionAggregation(string name, SingleBucketsPath bucketsPath)
22+
: base(name, bucketsPath) { }
23+
24+
internal override void WrapInContainer(AggregationContainer c) => c.MovingFunction = this;
25+
26+
public int? Window { get; set; }
27+
public string Script { get; set; }
28+
}
29+
30+
public class MovingFunctionAggregationDescriptor
31+
: PipelineAggregationDescriptorBase<MovingFunctionAggregationDescriptor, IMovingFunctionAggregation, SingleBucketsPath>
32+
, IMovingFunctionAggregation
33+
{
34+
int? IMovingFunctionAggregation.Window { get; set; }
35+
string IMovingFunctionAggregation.Script { get; set; }
36+
37+
public MovingFunctionAggregationDescriptor Window(int? windowSize) => Assign(a => a.Window = windowSize);
38+
39+
public MovingFunctionAggregationDescriptor Script(string script) => Assign(a => a.Script = script);
40+
}
41+
}

src/Nest/Aggregations/Pipeline/PipelineAggregationBase.cs

+1-4
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@ public abstract class PipelineAggregationBase : AggregationBase, IPipelineAggreg
2020
{
2121
internal PipelineAggregationBase() { }
2222

23-
public PipelineAggregationBase(string name, IBucketsPath bucketsPath) : base(name)
24-
{
25-
this.BucketsPath = bucketsPath;
26-
}
23+
public PipelineAggregationBase(string name, IBucketsPath bucketsPath) : base(name) => this.BucketsPath = bucketsPath;
2724

2825
public IBucketsPath BucketsPath { get; set; }
2926
public string Format { get; set; }

src/Tests/Tests/Aggregations/Pipeline/MovingAverage/MovingAverageSimpleAggregationUsageTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ protected override void ExpectResponse(ISearchResponse<Project> response)
9393
projectsPerMonth.Buckets.Should().NotBeNull();
9494
projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0);
9595

96-
// average not calculated for the first bucket
96+
// average not calculated for the first bucket so movingAvg.Value is expected to be null there
9797
foreach(var item in projectsPerMonth.Buckets.Skip(1))
9898
{
9999
var movingAvg = item.Sum("commits_moving_avg");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
using System;
2+
using System.Linq;
3+
using Elastic.Xunit.XunitPlumbing;
4+
using FluentAssertions;
5+
using Nest;
6+
using Tests.Core.Extensions;
7+
using Tests.Core.ManagedElasticsearch.Clusters;
8+
using Tests.Domain;
9+
using Tests.Framework;
10+
using Tests.Framework.Integration;
11+
12+
namespace Tests.Aggregations.Pipeline.MovingFunction
13+
{
14+
public class MovingFunctionAggregationUsageTests : AggregationUsageTestBase
15+
{
16+
public MovingFunctionAggregationUsageTests(ReadOnlyCluster cluster, EndpointUsage usage) : base(cluster, usage) { }
17+
18+
protected override object AggregationJson => new
19+
{
20+
projects_started_per_month = new
21+
{
22+
date_histogram = new
23+
{
24+
field = "startedOn",
25+
interval = "month",
26+
},
27+
aggs = new
28+
{
29+
commits = new
30+
{
31+
sum = new
32+
{
33+
field = "numberOfCommits"
34+
}
35+
},
36+
commits_moving_avg = new
37+
{
38+
moving_fn = new
39+
{
40+
buckets_path = "commits",
41+
window = 30,
42+
script = "MovingFunctions.unweightedAvg(values)"
43+
}
44+
}
45+
}
46+
}
47+
};
48+
49+
protected override Func<AggregationContainerDescriptor<Project>, IAggregationContainer> FluentAggs => a => a
50+
.DateHistogram("projects_started_per_month", dh => dh
51+
.Field(p => p.StartedOn)
52+
.Interval(DateInterval.Month)
53+
.Aggregations(aa => aa
54+
.Sum("commits", sm => sm
55+
.Field(p => p.NumberOfCommits)
56+
)
57+
.MovingFunction("commits_moving_avg", mv => mv
58+
.BucketsPath("commits")
59+
.Window(30)
60+
.Script("MovingFunctions.unweightedAvg(values)")
61+
)
62+
)
63+
);
64+
65+
protected override AggregationDictionary InitializerAggs =>
66+
new DateHistogramAggregation("projects_started_per_month")
67+
{
68+
Field = "startedOn",
69+
Interval = DateInterval.Month,
70+
Aggregations =
71+
new SumAggregation("commits", "numberOfCommits")
72+
&& new MovingFunctionAggregation("commits_moving_avg", "commits")
73+
{
74+
Window = 30,
75+
Script = "MovingFunctions.unweightedAvg(values)"
76+
}
77+
};
78+
79+
protected override void ExpectResponse(ISearchResponse<Project> response)
80+
{
81+
response.ShouldBeValid();
82+
83+
var projectsPerMonth = response.Aggregations.DateHistogram("projects_started_per_month");
84+
projectsPerMonth.Should().NotBeNull();
85+
projectsPerMonth.Buckets.Should().NotBeNull();
86+
projectsPerMonth.Buckets.Count.Should().BeGreaterThan(0);
87+
88+
// average not calculated for the first bucket
89+
foreach(var item in projectsPerMonth.Buckets.Skip(1))
90+
{
91+
var movingAvg = item.Sum("commits_moving_avg");
92+
movingAvg.Should().NotBeNull();
93+
movingAvg.Value.Should().BeGreaterThan(0);
94+
}
95+
}
96+
}
97+
}

0 commit comments

Comments
 (0)