Skip to content

Commit

Permalink
feat: Implement 'Auto Date Histogram' (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
sudo-suhas authored Jul 4, 2020
2 parents 1e7cc73 + 60a1ff1 commit 9fd46a4
Show file tree
Hide file tree
Showing 7 changed files with 313 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ toc:
- name: Bucket Aggregations
- BucketAggregationBase
- AdjacencyMatrixAggregation
- AutoDateHistogramAggregation
- ChildrenAggregation
- CompositeAggregation
- name: Values Source
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
'use strict';

const isNil = require('lodash.isnil');

const BucketAggregationBase = require('./bucket-aggregation-base');

/**
* 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.
*
* [Elasticsearch reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-autodatehistogram-aggregation.html)
*
* @example
* const agg = esb.autoDateHistogramAggregation('sales_over_time', 'date', 15);
*
* @param {string} name The name which will be used to refer to this aggregation.
* @param {string} field The field to aggregate on
* @param {number} buckets Bucket count to generate histogram over.
*
* @extends BucketAggregationBase
*/
class AutoDateHistogramAggregation extends BucketAggregationBase {
// eslint-disable-next-line require-jsdoc
constructor(name, field, buckets) {
super(name, 'auto_date_histogram', field);
if (!isNil(buckets)) this._aggsDef.buckets = buckets;
}

/**
* Sets the histogram bucket count. Buckets are generated based on this value.
*
* @param {number} buckets Bucket count to generate histogram over.
* @returns {AutoDateHistogramAggregation} returns `this` so that calls can be chained
*/
buckets(buckets) {
this._aggsDef.buckets = buckets;
return this;
}

/**
* The minimum_interval allows the caller to specify the minimum rounding interval that
* should be used. This can make the collection process more efficient, as the
* aggregation will not attempt to round at any interval lower than minimum_interval.
*
* Accepted units: year, month, day, hour, minute, second
*
* [Elasticsearch reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-autodatehistogram-aggregation.html#_minimum_interval_parameter)
*
* @example
* const agg = esb.autoDateHistogramAggregation(
* 'sales_over_time',
* 'date',
* 5
* ).minimumInterval('minute');
*
* @param {string} interval Minimum Rounding Interval Example: 'minute'
* @returns {AutoDateHistogramAggregation} returns `this` so that calls can be chained
*/
minimumInterval(interval) {
this._aggsDef.minimum_interval = interval;
return this;
}

/**
* Sets the format expression for `key_as_string` in response buckets.
* If no format is specified, then it will use the first format specified in the field mapping.
*
* @example
* const agg = esb.autoDateHistogramAggregation(
* 'sales_over_time',
* 'date',
* 5
* ).format('yyyy-MM-dd');
*
* @param {string} fmt Format mask to apply on aggregation response. Example: ####.00.
* For Date Histograms, supports expressive [date format pattern](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-daterange-aggregation.html#date-format-pattern)
* @returns {AutoDateHistogramAggregation} returns `this` so that calls can be chained
*/
format(fmt) {
this._aggsDef.format = fmt;
return this;
}

/**
* Sets the missing parameter which defines how documents
* that are missing a value should be treated.
*
* @example
* const agg = esb.autoDateHistogramAggregation('quantity', 'quantity', 10).missing(0);
*
* @param {string} value
* @returns {AutoDateHistogramAggregation} returns `this` so that calls can be chained
*/
missing(value) {
this._aggsDef.missing = value;
return this;
}

/**
* Date-times are stored in Elasticsearch in UTC.
* By default, all bucketing and rounding is also done in UTC.
* The `time_zone` parameter can be used to indicate that bucketing should use a different time zone.
* Sets the date time zone
*
* @example
* const agg = esb.autoDateHistogramAggregation('by_day', 'date', 15).timeZone(
* '-01:00'
* );
*
* @param {string} tz Time zone. Time zones may either be specified
* as an ISO 8601 UTC offset (e.g. +01:00 or -08:00) or as a timezone id,
* an identifier used in the TZ database like America/Los_Angeles.
* @returns {AutoDateHistogramAggregation} returns `this` so that calls can be chained
*/
timeZone(tz) {
this._aggsDef.time_zone = tz;
return this;
}
}

module.exports = AutoDateHistogramAggregation;
1 change: 1 addition & 0 deletions src/aggregations/bucket-aggregations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exports.AdjacencyMatrixAggregation = require('./adjacency-matrix-aggregation');
exports.ChildrenAggregation = require('./children-aggregation');
exports.CompositeAggregation = require('./composite-aggregation');
exports.DateHistogramAggregation = require('./date-histogram-aggregation');
exports.AutoDateHistogramAggregation = require('./auto-date-histogram-aggregation');
exports.DateRangeAggregation = require('./date-range-aggregation');
exports.DiversifiedSamplerAggregation = require('./diversified-sampler-aggregation');
exports.FilterAggregation = require('./filter-aggregation');
Expand Down
77 changes: 77 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4918,6 +4918,83 @@ declare namespace esb {
keyed(keyed: boolean): this;
}

/**
* The `AutoDateHistogramAggregation` is 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.
*
* @param {string} name The name which will be used to refer to this aggregation.
* @param {string} aggType Type of aggregation
* @param {string=} field The field to aggregate on
* @param {number=} buckets Bucket count to generate histogram over.
* @extends BucketAggregationBase
*/
export class AutoDateHistogramAggregation extends BucketAggregationBase {
constructor(
name: string,
field?: string,
buckets?: number
);

/**
* Sets the bucket count. Buckets are generated based on this interval value.
*
* @param {number} buckets Bucket count to generate histogram over.
*/
buckets(buckets: number): this;

/**
* Sets the format expression for `key_as_string` in response buckets.
* If no format is specified, then it will use the first format specified in the field mapping.
*
* @param {string} fmt Format mask to apply on aggregation response. Example: ####.00.
* For Date Histograms, supports expressive date format pattern
*/
format(fmt: string): this;

/**
* Sets the missing parameter which defines how documents
* that are missing a value should be treated.
*
* @param {string} value
*/
missing(value: string): this;

/**
* Sets the minimum rounding interval that should be used.
*
* @param {string} value
*/
minimumInterval(value: string): this;

/**
* Date-times are stored in Elasticsearch in UTC.
* By default, all bucketing and rounding is also done in UTC.
* The `time_zone` parameter can be used to indicate that bucketing should use a different time zone.
* Sets the date time zone
*
* @param {string} tz Time zone. Time zones may either be specified
* as an ISO 8601 UTC offset (e.g. +01:00 or -08:00) or as a timezone id,
* an identifier used in the TZ database like America/Los_Angeles.
*/
timeZone(tz: string): this;
}

/**
* A multi-bucket aggregation similar to the histogram except it can only be applied on date values.
* The interval can be specified by date/time expressions.
*
* @param {string} name The name which will be used to refer to this aggregation.
* @param {string=} field The field to aggregate on
* @param {number=} buckets Bucket count to generate histogram over.
*/
export function autoDateHistogramAggregation(
name: string,
field?: string,
buckets?: number
): AutoDateHistogramAggregation;

/**
* A multi-bucket aggregation similar to the histogram except it can only be applied on date values.
* The interval can be specified by date/time expressions.
Expand Down
6 changes: 6 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ const {
ChildrenAggregation,
CompositeAggregation,
DateHistogramAggregation,
AutoDateHistogramAggregation,
DateRangeAggregation,
DiversifiedSamplerAggregation,
FilterAggregation,
Expand Down Expand Up @@ -376,6 +377,11 @@ exports.compositeAggregation = constructorWrapper(CompositeAggregation);
exports.DateHistogramAggregation = DateHistogramAggregation;
exports.dateHistogramAggregation = constructorWrapper(DateHistogramAggregation);

exports.AutoDateHistogramAggregation = AutoDateHistogramAggregation;
exports.autoDateHistogramAggregation = constructorWrapper(
AutoDateHistogramAggregation
);

exports.DateRangeAggregation = DateRangeAggregation;
exports.dateRangeAggregation = constructorWrapper(DateRangeAggregation);

Expand Down
101 changes: 101 additions & 0 deletions test/aggregations-test/auto-date-histogram-agg.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import test from 'ava';
import { AutoDateHistogramAggregation } from '../../src';
import { setsAggType } from '../_macros';

test(setsAggType, AutoDateHistogramAggregation, 'auto_date_histogram');

test('constructor sets arguments', t => {
const value = new AutoDateHistogramAggregation(
'sale_date',
'date',
10
).toJSON(),
expected = {
sale_date: {
auto_date_histogram: {
field: 'date',
buckets: 10
}
}
};
t.deepEqual(value, expected);
});

test('buckets is set', t => {
const value = new AutoDateHistogramAggregation('by_day', 'date', 10)
.buckets(20)
.toJSON();
const expected = {
by_day: {
auto_date_histogram: {
field: 'date',
buckets: 20
}
}
};
t.deepEqual(value, expected);
});

test('format is set', t => {
const value = new AutoDateHistogramAggregation('by_day', 'date', 10)
.format('yyyy-MM-dd')
.toJSON();
const expected = {
by_day: {
auto_date_histogram: {
field: 'date',
buckets: 10,
format: 'yyyy-MM-dd'
}
}
};
t.deepEqual(value, expected);
});

test('minimum_interval is set', t => {
const value = new AutoDateHistogramAggregation('by_day', 'date', 10)
.minimumInterval('minute')
.toJSON();
const expected = {
by_day: {
auto_date_histogram: {
field: 'date',
buckets: 10,
minimum_interval: 'minute'
}
}
};
t.deepEqual(value, expected);
});

test('time_zone is set', t => {
const value = new AutoDateHistogramAggregation('by_day', 'date', 10)
.timeZone('-01:00')
.toJSON();
const expected = {
by_day: {
auto_date_histogram: {
field: 'date',
buckets: 10,
time_zone: '-01:00'
}
}
};
t.deepEqual(value, expected);
});

test('missing is set', t => {
const value = new AutoDateHistogramAggregation('by_day', 'date', 10)
.missing('2000/01/01')
.toJSON();
const expected = {
by_day: {
auto_date_histogram: {
field: 'date',
buckets: 10,
missing: '2000/01/01'
}
}
};
t.deepEqual(value, expected);
});
3 changes: 3 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ test('aggregations are exported', t => {
t.truthy(esb.DateHistogramAggregation);
t.truthy(esb.dateHistogramAggregation);

t.truthy(esb.AutoDateHistogramAggregation);
t.truthy(esb.autoDateHistogramAggregation);

t.truthy(esb.DateRangeAggregation);
t.truthy(esb.dateRangeAggregation);

Expand Down

0 comments on commit 9fd46a4

Please sign in to comment.