-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for the auto_date_histogram aggregation elastic/elasticse…
- Loading branch information
Showing
8 changed files
with
273 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
src/Nest/Aggregations/Bucket/AutoDateHistogram/AutoDateHistogramAggregation.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq.Expressions; | ||
using Newtonsoft.Json; | ||
|
||
namespace Nest | ||
{ | ||
[JsonObject(MemberSerialization = MemberSerialization.OptIn)] | ||
[ContractJsonConverter(typeof(AggregationJsonConverter<AutoDateHistogramAggregation>))] | ||
public interface IAutoDateHistogramAggregation : IBucketAggregation | ||
{ | ||
[JsonProperty("field")] | ||
Field Field { get; set; } | ||
|
||
[JsonProperty("format")] | ||
string Format { get; set; } | ||
|
||
[JsonProperty("missing")] | ||
DateTime? Missing { get; set; } | ||
|
||
[JsonProperty("offset")] | ||
string Offset { get; set; } | ||
|
||
[JsonProperty("params")] | ||
IDictionary<string, object> Params { get; set; } | ||
|
||
[JsonProperty("script")] | ||
IScript Script { get; set; } | ||
|
||
[JsonProperty("time_zone")] | ||
string TimeZone { get; set; } | ||
} | ||
|
||
public class AutoDateHistogramAggregation : BucketAggregationBase, IAutoDateHistogramAggregation | ||
{ | ||
private string _format; | ||
|
||
internal AutoDateHistogramAggregation() { } | ||
|
||
public AutoDateHistogramAggregation(string name) : base(name) { } | ||
|
||
public Field Field { get; set; } | ||
|
||
//see: https://github.com/elastic/elasticsearch/issues/9725 | ||
public string Format | ||
{ | ||
get => !string.IsNullOrEmpty(_format) && | ||
!_format.Contains("date_optional_time") && | ||
(Missing.HasValue) | ||
? _format + "||date_optional_time" | ||
: _format; | ||
set => _format = value; | ||
} | ||
|
||
public DateTime? Missing { get; set; } | ||
public string Offset { get; set; } | ||
public IDictionary<string, object> Params { get; set; } | ||
public IScript Script { get; set; } | ||
public string TimeZone { get; set; } | ||
|
||
internal override void WrapInContainer(AggregationContainer c) => c.AutoDateHistogram = this; | ||
} | ||
|
||
public class AutoDateHistogramAggregationDescriptor<T> | ||
: BucketAggregationDescriptorBase<AutoDateHistogramAggregationDescriptor<T>, IAutoDateHistogramAggregation, T> | ||
, IAutoDateHistogramAggregation | ||
where T : class | ||
{ | ||
private string _format; | ||
|
||
Field IAutoDateHistogramAggregation.Field { get; set; } | ||
|
||
//see: https://github.com/elastic/elasticsearch/issues/9725 | ||
string IAutoDateHistogramAggregation.Format | ||
{ | ||
get => !string.IsNullOrEmpty(_format) && | ||
!_format.Contains("date_optional_time") && | ||
(Self.Missing.HasValue) | ||
? _format + "||date_optional_time" | ||
: _format; | ||
set => _format = value; | ||
} | ||
|
||
DateTime? IAutoDateHistogramAggregation.Missing { get; set; } | ||
|
||
string IAutoDateHistogramAggregation.Offset { get; set; } | ||
|
||
IDictionary<string, object> IAutoDateHistogramAggregation.Params { get; set; } | ||
|
||
IScript IAutoDateHistogramAggregation.Script { get; set; } | ||
|
||
string IAutoDateHistogramAggregation.TimeZone { get; set; } | ||
|
||
public AutoDateHistogramAggregationDescriptor<T> Field(Field field) => Assign(a => a.Field = field); | ||
|
||
public AutoDateHistogramAggregationDescriptor<T> Field(Expression<Func<T, object>> field) => Assign(a => a.Field = field); | ||
|
||
public AutoDateHistogramAggregationDescriptor<T> Script(string script) => Assign(a => a.Script = (InlineScript)script); | ||
|
||
public AutoDateHistogramAggregationDescriptor<T> Script(Func<ScriptDescriptor, IScript> scriptSelector) => | ||
Assign(a => a.Script = scriptSelector?.Invoke(new ScriptDescriptor())); | ||
|
||
public AutoDateHistogramAggregationDescriptor<T> Format(string format) => Assign(a => a.Format = format); | ||
|
||
public AutoDateHistogramAggregationDescriptor<T> TimeZone(string timeZone) => Assign(a => a.TimeZone = timeZone); | ||
|
||
public AutoDateHistogramAggregationDescriptor<T> Offset(string offset) => Assign(a => a.Offset = offset); | ||
|
||
public AutoDateHistogramAggregationDescriptor<T> Missing(DateTime? missing) => Assign(a => a.Missing = missing); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/Nest/Aggregations/Bucket/AutoDateHistogram/AutoDateHistogramBucket.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
namespace Nest | ||
{ | ||
public class AutoDateHistogramAggregate : MultiBucketAggregate<DateHistogramBucket> | ||
{ | ||
public Time Interval { get; internal set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
...sts/Tests/Aggregations/Bucket/AutoDateHistogram/AutoDateHistogramAggregationUsageTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
using System; | ||
using System.Linq; | ||
using FluentAssertions; | ||
using Nest; | ||
using Tests.Core.Extensions; | ||
using Tests.Core.ManagedElasticsearch.Clusters; | ||
using Tests.Domain; | ||
using Tests.Framework.Integration; | ||
using static Nest.Infer; | ||
using static Tests.Domain.Helpers.TestValueHelper; | ||
|
||
namespace Tests.Aggregations.Bucket.AutoDateHistogram | ||
{ | ||
/** | ||
* A multi-bucket aggregation similar to the Date Histogram Aggregation except instead of providing an interval to | ||
* use as the width of each bucket, a target number of buckets is provided indicating the number of buckets needed | ||
* and the interval of the buckets is automatically chosen to best achieve that target. The number of buckets | ||
* returned will always be less than or equal to this target number. | ||
* | ||
* NOTE: When specifying a `format` **and** `extended_bounds` or `missing`, in order for Elasticsearch to be able to parse | ||
* the serialized `DateTime` of `extended_bounds` or `missing` correctly, the `date_optional_time` format is included | ||
* as part of the `format` value. | ||
* | ||
* Be sure to read the Elasticsearch documentation on {ref_current}/search-aggregations-bucket-autodatehistogram-aggregation.html[Auto Date Histogram Aggregation]. | ||
*/ | ||
public class AutoDateHistogramAggregationUsageTests : ProjectsOnlyAggregationUsageTestBase | ||
{ | ||
public AutoDateHistogramAggregationUsageTests(ReadOnlyCluster i, EndpointUsage usage) : base(i, usage) { } | ||
|
||
protected override object AggregationJson => new | ||
{ | ||
projects_started_per_month = new | ||
{ | ||
auto_date_histogram = new | ||
{ | ||
field = "startedOn", | ||
format = "yyyy-MM-dd'T'HH:mm:ss||date_optional_time", //<1> Note the inclusion of `date_optional_time` to `format` | ||
missing = FixedDate | ||
}, | ||
aggs = new | ||
{ | ||
project_tags = new | ||
{ | ||
nested = new | ||
{ | ||
path = "tags" | ||
}, | ||
aggs = new | ||
{ | ||
tags = new | ||
{ | ||
terms = new { field = "tags.name" } | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
|
||
protected override Func<AggregationContainerDescriptor<Project>, IAggregationContainer> FluentAggs => a => a | ||
.AutoDateHistogram("projects_started_per_month", date => date | ||
.Field(p => p.StartedOn) | ||
.Format("yyyy-MM-dd'T'HH:mm:ss") | ||
.Missing(FixedDate) | ||
.Aggregations(childAggs => childAggs | ||
.Nested("project_tags", n => n | ||
.Path(p => p.Tags) | ||
.Aggregations(nestedAggs => nestedAggs | ||
.Terms("tags", avg => avg.Field(p => p.Tags.First().Name)) | ||
) | ||
) | ||
) | ||
); | ||
|
||
protected override AggregationDictionary InitializerAggs => | ||
new AutoDateHistogramAggregation("projects_started_per_month") | ||
{ | ||
Field = Field<Project>(p => p.StartedOn), | ||
Format = "yyyy-MM-dd'T'HH:mm:ss", | ||
Missing = FixedDate, | ||
Aggregations = new NestedAggregation("project_tags") | ||
{ | ||
Path = Field<Project>(p => p.Tags), | ||
Aggregations = new TermsAggregation("tags") | ||
{ | ||
Field = Field<Project>(p => p.Tags.First().Name) | ||
} | ||
} | ||
}; | ||
|
||
protected override void ExpectResponse(ISearchResponse<Project> response) | ||
{ | ||
/** ==== Handling responses | ||
* The `AggregateDictionary found on `.Aggregations` on `ISearchResponse<T>` has several helper methods | ||
* so we can fetch our aggregation results easily in the correct type. | ||
* <<handling-aggregate-response, Be sure to read more about these helper methods>> | ||
*/ | ||
response.ShouldBeValid(); | ||
|
||
var dateHistogram = response.Aggregations.AutoDateHistogram("projects_started_per_month"); | ||
dateHistogram.Should().NotBeNull(); | ||
dateHistogram.Interval.Should().NotBeNull(); | ||
dateHistogram.Buckets.Should().NotBeNull(); | ||
dateHistogram.Buckets.Count.Should().BeGreaterThan(1); | ||
foreach (var item in dateHistogram.Buckets) | ||
{ | ||
item.Date.Should().NotBe(default); | ||
item.DocCount.Should().BeGreaterThan(0); | ||
|
||
var nested = item.Nested("project_tags"); | ||
nested.Should().NotBeNull(); | ||
|
||
var nestedTerms = nested.Terms("tags"); | ||
nestedTerms.Buckets.Count.Should().BeGreaterThan(0); | ||
} | ||
} | ||
} | ||
} |