Skip to content

Commit d492993

Browse files
authored
Add variable width histogram aggregation (#5402)
1 parent 9cc8548 commit d492993

File tree

12 files changed

+338
-4
lines changed

12 files changed

+338
-4
lines changed

docs/aggregations.asciidoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ In addition to the buckets themselves, the bucket aggregations also compute and
188188

189189
* <<terms-aggregation-usage,Terms Aggregation Usage>>
190190

191+
* <<variable-width-histogram-usage,Variable Width Histogram Usage>>
192+
191193
[NOTE]
192194
--
193195
Bucketing aggregations can have sub-aggregations (bucketing or metric). The sub-aggregations will be computed
@@ -253,6 +255,8 @@ include::aggregations/bucket/significant-text/significant-text-aggregation-usage
253255

254256
include::aggregations/bucket/terms/terms-aggregation-usage.asciidoc[]
255257

258+
include::aggregations/bucket/variable-width-histogram/variable-width-histogram-usage.asciidoc[]
259+
256260
[[pipeline-aggregations]]
257261
== Pipeline Aggregations
258262

docs/aggregations/bucket/multi-terms/multi-terms-aggregation-usage.asciidoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ please modify the original csharp file found at the link and submit the PR with
1717

1818
A multi-bucket value source based aggregation where buckets are dynamically built - one per unique set of values.
1919

20-
See the Elasticsearch documentation on {ref_current}//search-aggregations-bucket-multi-terms-aggregation.html[multi terms aggregation] for more detail.
20+
See the Elasticsearch documentation on {ref_current}/search-aggregations-bucket-multi-terms-aggregation.html[multi terms aggregation] for more detail.
2121

2222
==== Fluent DSL example
2323

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
:ref_current: https://www.elastic.co/guide/en/elasticsearch/reference/7.x
2+
3+
:github: https://github.com/elastic/elasticsearch-net
4+
5+
:nuget: https://www.nuget.org/packages
6+
7+
////
8+
IMPORTANT NOTE
9+
==============
10+
This file has been generated from https://github.com/elastic/elasticsearch-net/tree/7.x/src/Tests/Tests/Aggregations/Bucket/VariableWidthHistogram/VariableWidthHistogramUsageTests.cs.
11+
If you wish to submit a PR for any spelling mistakes, typos or grammatical errors for this file,
12+
please modify the original csharp file found at the link and submit the PR with that change. Thanks!
13+
////
14+
15+
[[variable-width-histogram-usage]]
16+
=== Variable Width Histogram Usage
17+
18+
A multi-bucket aggregation similar to Histogram. However, the width of each bucket is not specified. Rather, a target number of buckets is provided
19+
and bucket intervals are dynamically determined based on the document distribution.
20+
21+
See the Elasticsearch documentation on {ref_current}/search-aggregations-bucket-variablewidthhistogram-aggregation.html[multi terms aggregation] for more detail.
22+
23+
==== Fluent DSL example
24+
25+
[source,csharp]
26+
----
27+
a => a
28+
.VariableWidthHistogram("commits", v => v
29+
.Field(f => f.NumberOfCommits)
30+
.Buckets(2)
31+
.InitialBuffer(2)
32+
.ShardSize(100)
33+
.Meta(m => m
34+
.Add("foo", "bar")
35+
))
36+
----
37+
38+
==== Object Initializer syntax example
39+
40+
[source,csharp]
41+
----
42+
new VariableWidthHistogramAggregation("commits")
43+
{
44+
Field = Field<Project>(f => f.NumberOfCommits),
45+
Buckets = 2,
46+
InitialBuffer = 2,
47+
ShardSize = 100,
48+
Meta = new Dictionary<string, object>
49+
{
50+
{ "foo", "bar" }
51+
}
52+
}
53+
----
54+
55+
[source,javascript]
56+
.Example json output
57+
----
58+
{
59+
"commits": {
60+
"meta": {
61+
"foo": "bar"
62+
},
63+
"variable_width_histogram": {
64+
"field": "numberOfCommits",
65+
"buckets": 2,
66+
"initial_buffer": 2,
67+
"shard_size": 100
68+
}
69+
}
70+
}
71+
----
72+
73+
==== Handling Responses
74+
75+
[source,csharp]
76+
----
77+
response.ShouldBeValid();
78+
var counts = response.Aggregations.VariableWidthHistogram("commits");
79+
counts.Should().NotBeNull();
80+
counts.Buckets.Should().HaveCountGreaterThan(0);
81+
var firstBucket = counts.Buckets.First();
82+
firstBucket.Key.Should().BeGreaterOrEqualTo(0);
83+
firstBucket.Minimum.Should().BeGreaterOrEqualTo(0);
84+
firstBucket.Maximum.Should().BeGreaterOrEqualTo(0);
85+
firstBucket.DocCount.Should().BeGreaterOrEqualTo(1);
86+
counts.Meta.Should().NotBeNull().And.HaveCount(1);
87+
counts.Meta["foo"].Should().Be("bar");
88+
----
89+

src/Nest/Aggregations/AggregateDictionary.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ public MultiBucketAggregate<RareTermsBucket<TKey>> RareTerms<TKey>(string key)
222222

223223
public MultiBucketAggregate<DateHistogramBucket> DateHistogram(string key) => GetMultiBucketAggregate<DateHistogramBucket>(key);
224224

225+
public MultiBucketAggregate<VariableWidthHistogramBucket> VariableWidthHistogram(string key) => GetMultiBucketAggregate<VariableWidthHistogramBucket>(key);
226+
225227
public MultiTermsAggregate<string> MultiTerms(string key) => MultiTerms<string>(key);
226228

227229
public MultiTermsAggregate<TKey> MultiTerms<TKey>(string key)

src/Nest/Aggregations/AggregateFormatter.cs

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ internal class AggregateFormatter : IJsonFormatter<IAggregate>
2525
{ Parser.From, 1 },
2626
{ Parser.To, 2 },
2727
{ Parser.KeyAsString, 3 },
28-
{ Parser.DocCount, 4 }
28+
{ Parser.DocCount, 4 },
29+
{ Parser.Min, 5 }
2930
};
3031

3132
private static readonly byte[] BucketsField = JsonWriter.GetEncodedPropertyNameWithoutQuotation(Parser.Buckets);
@@ -219,6 +220,9 @@ private IBucket ReadBucket(ref JsonReader reader, IJsonFormatterResolver formatt
219220
case 4:
220221
item = GetFiltersBucket(ref reader, formatterResolver);
221222
break;
223+
case 5:
224+
item = GetVariableWidthHistogramBucket(ref reader, formatterResolver);
225+
break;
222226
}
223227
}
224228
else
@@ -941,7 +945,42 @@ private IBucket GetDateHistogramBucket(ref JsonReader reader, IJsonFormatterReso
941945

942946
return dateHistogram;
943947
}
944-
948+
949+
private IBucket GetVariableWidthHistogramBucket(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
950+
{
951+
var min = reader.ReadDouble();
952+
reader.ReadNext(); // ,
953+
reader.ReadNext(); // "key"
954+
reader.ReadNext(); // :
955+
var key = reader.ReadDouble();
956+
reader.ReadNext(); // ,
957+
reader.ReadNext(); // "max"
958+
reader.ReadNext(); // :
959+
var max = reader.ReadDouble();
960+
reader.ReadNext(); // ,
961+
reader.ReadNext(); // "doc_count"
962+
reader.ReadNext(); // :
963+
var docCount = reader.ReadInt64();
964+
965+
Dictionary<string, IAggregate> subAggregates = null;
966+
if (reader.GetCurrentJsonToken() == JsonToken.ValueSeparator)
967+
{
968+
reader.ReadNext(); // ,
969+
var propertyName = reader.ReadPropertyName();
970+
subAggregates = GetSubAggregates(ref reader, propertyName, formatterResolver);
971+
}
972+
973+
var variableWidthHistogram = new VariableWidthHistogramBucket(subAggregates)
974+
{
975+
Key = key,
976+
Minimum = min,
977+
Maximum = max,
978+
DocCount = docCount,
979+
};
980+
981+
return variableWidthHistogram;
982+
}
983+
945984
private IBucket GetKeyedBucket(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
946985
{
947986
var token = reader.GetCurrentJsonToken();

src/Nest/Aggregations/AggregationContainer.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ public interface IAggregationContainer
295295

296296
[DataMember(Name = "multi_terms")]
297297
IMultiTermsAggregation MultiTerms { get; set; }
298+
299+
[DataMember(Name = "variable_width_histogram")]
300+
IVariableWidthHistogramAggregation VariableWidthHistogram { get; set; }
298301

299302
void Accept(IAggregationVisitor visitor);
300303
}
@@ -446,6 +449,8 @@ public class AggregationContainer : IAggregationContainer
446449

447450
public IMultiTermsAggregation MultiTerms { get; set; }
448451

452+
public IVariableWidthHistogramAggregation VariableWidthHistogram { get; set; }
453+
449454
public void Accept(IAggregationVisitor visitor)
450455
{
451456
if (visitor.Scope == AggregationVisitorScope.Unknown) visitor.Scope = AggregationVisitorScope.Aggregation;
@@ -615,6 +620,8 @@ public class AggregationContainerDescriptor<T> : DescriptorBase<AggregationConta
615620

616621
ITopMetricsAggregation IAggregationContainer.TopMetrics { get; set; }
617622

623+
IVariableWidthHistogramAggregation IAggregationContainer.VariableWidthHistogram { get; set; }
624+
618625
public void Accept(IAggregationVisitor visitor)
619626
{
620627
if (visitor.Scope == AggregationVisitorScope.Unknown) visitor.Scope = AggregationVisitorScope.Aggregation;
@@ -960,6 +967,11 @@ Func<TopMetricsAggregationDescriptor<T>, ITopMetricsAggregation> selector
960967
) =>
961968
_SetInnerAggregation(name, selector, (a, d) => a.TopMetrics = d);
962969

970+
public AggregationContainerDescriptor<T> VariableWidthHistogram(string name,
971+
Func<VariableWidthHistogramAggregationDescriptor<T>, IVariableWidthHistogramAggregation> selector
972+
) =>
973+
_SetInnerAggregation(name, selector, (a, d) => a.VariableWidthHistogram = d);
974+
963975
/// <summary>
964976
/// Fluent methods do not assign to properties on `this` directly but on IAggregationContainers inside
965977
/// `this.Aggregations[string, IContainer]
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System;
6+
using System.Linq.Expressions;
7+
using System.Runtime.Serialization;
8+
using Elasticsearch.Net.Utf8Json;
9+
10+
namespace Nest
11+
{
12+
[InterfaceDataContract]
13+
[ReadAs(typeof(VariableWidthHistogramAggregation))]
14+
public interface IVariableWidthHistogramAggregation : IBucketAggregation
15+
{
16+
/// <summary>
17+
/// The field to target.
18+
/// </summary>
19+
[DataMember(Name = "field")]
20+
Field Field { get; set; }
21+
22+
[DataMember(Name = "buckets")]
23+
int? Buckets { get; set; }
24+
25+
[DataMember(Name = "initial_buffer")]
26+
int? InitialBuffer { get; set; }
27+
28+
[DataMember(Name = "shard_size")]
29+
int? ShardSize { get; set; }
30+
}
31+
32+
public class VariableWidthHistogramAggregation : BucketAggregationBase, IVariableWidthHistogramAggregation
33+
{
34+
public VariableWidthHistogramAggregation(string name) : base(name) { }
35+
36+
/// <inheritdoc />
37+
public Field Field { get; set; }
38+
/// <inheritdoc />
39+
public int? Buckets { get; set; }
40+
/// <inheritdoc />
41+
public int? InitialBuffer { get; set; }
42+
/// <inheritdoc />
43+
public int? ShardSize { get; set; }
44+
45+
internal override void WrapInContainer(AggregationContainer c) => c.VariableWidthHistogram = this;
46+
}
47+
48+
public class VariableWidthHistogramAggregationDescriptor<T>
49+
: BucketAggregationDescriptorBase<VariableWidthHistogramAggregationDescriptor<T>, IVariableWidthHistogramAggregation, T>, IVariableWidthHistogramAggregation
50+
where T : class
51+
{
52+
Field IVariableWidthHistogramAggregation.Field { get; set; }
53+
int? IVariableWidthHistogramAggregation.Buckets { get; set; }
54+
int? IVariableWidthHistogramAggregation.InitialBuffer { get; set; }
55+
int? IVariableWidthHistogramAggregation.ShardSize { get; set; }
56+
57+
/// <inheritdoc cref="IVariableWidthHistogramAggregation.Field" />
58+
public VariableWidthHistogramAggregationDescriptor<T> Field(Field field) => Assign(field, (a, v) => a.Field = v);
59+
60+
/// <inheritdoc cref="IVariableWidthHistogramAggregation.Field" />
61+
public VariableWidthHistogramAggregationDescriptor<T> Field<TValue>(Expression<Func<T, TValue>> field) => Assign(field, (a, v) => a.Field = v);
62+
63+
/// <inheritdoc cref="IVariableWidthHistogramAggregation.Buckets" />
64+
public VariableWidthHistogramAggregationDescriptor<T> Buckets(int? buckets) => Assign(buckets, (a, v) => a.Buckets = v);
65+
66+
/// <inheritdoc cref="IVariableWidthHistogramAggregation.InitialBuffer" />
67+
public VariableWidthHistogramAggregationDescriptor<T> InitialBuffer(int? initialBuffer) => Assign(initialBuffer, (a, v) => a.InitialBuffer = v);
68+
69+
/// <inheritdoc cref="IVariableWidthHistogramAggregation.ShardSize" />
70+
public VariableWidthHistogramAggregationDescriptor<T> ShardSize(int? shardSize) => Assign(shardSize, (a, v) => a.ShardSize = v);
71+
}
72+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Licensed to Elasticsearch B.V under one or more agreements.
2+
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3+
// See the LICENSE file in the project root for more information
4+
5+
using System.Collections.Generic;
6+
7+
namespace Nest
8+
{
9+
public class VariableWidthHistogramBucket : BucketBase
10+
{
11+
public VariableWidthHistogramBucket(IReadOnlyDictionary<string, IAggregate> dict) : base(dict) { }
12+
13+
public double Key { get; set; }
14+
15+
public double Minimum { get; set; }
16+
17+
public double Maximum { get; set; }
18+
19+
public long DocCount { get; set; }
20+
}
21+
}

src/Nest/Aggregations/Visitor/AggregationVisitor.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ public interface IAggregationVisitor
161161
void Visit(ITTestAggregation aggregation);
162162

163163
void Visit(IMultiTermsAggregation aggregation);
164+
165+
void Visit(IVariableWidthHistogramAggregation aggregation);
164166
}
165167

166168
public class AggregationVisitor : IAggregationVisitor
@@ -307,5 +309,7 @@ public virtual void Visit(IAggregation aggregation) { }
307309

308310
public virtual void Visit(IAggregationContainer aggregationContainer) { }
309311

312+
public virtual void Visit(IVariableWidthHistogramAggregation aggregationContainer) { }
313+
310314
}
311315
}

src/Nest/Aggregations/Visitor/AggregationWalker.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ public void Walk(IAggregationContainer aggregation, IAggregationVisitor visitor)
190190
AcceptAggregation(aggregation.Composite, visitor, (v, d) => v.Visit(d));
191191
AcceptAggregation(aggregation.MedianAbsoluteDeviation, visitor, (v, d) => v.Visit(d));
192192
AcceptAggregation(aggregation.TTest, visitor, (v, d) => v.Visit(d));
193+
AcceptAggregation(aggregation.VariableWidthHistogram, visitor, (v, d) =>
194+
{
195+
v.Visit(d);
196+
Accept(v, d.Aggregations);
197+
});
193198
}
194199
}
195200
}

0 commit comments

Comments
 (0)