-
-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Aggs): Start describing body.aggs input for
searchTyped
- Loading branch information
Showing
8 changed files
with
292 additions
and
2 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* @flow */ | ||
|
||
import { InputTypeComposer } from 'graphql-compose'; | ||
import { getTypeName, getOrSetType, desc } from '../../utils'; | ||
import { getAggRulesITC } from './AggRules'; | ||
|
||
export function getAggBlockITC(opts: mixed = {}): InputTypeComposer { | ||
const name = getTypeName('AggBlock', opts); | ||
const description = desc(` | ||
The aggregations framework helps provide aggregated data based on | ||
a search query. It is based on simple building blocks called aggregations, | ||
that can be composed in order to build complex summaries of the data. | ||
[Documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html) | ||
`); | ||
|
||
return getOrSetType(name, () => | ||
// $FlowFixMe | ||
InputTypeComposer.create({ | ||
name, | ||
description, | ||
fields: { | ||
key: { | ||
type: 'String', | ||
description: 'FieldName in response for aggregation result', | ||
}, | ||
value: { | ||
type: () => getAggRulesITC(opts), | ||
description: 'Aggregation rules', | ||
}, | ||
}, | ||
}) | ||
); | ||
} |
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,38 @@ | ||
/* @flow */ | ||
|
||
import { InputTypeComposer } from 'graphql-compose'; | ||
import { getTypeName, getOrSetType, desc } from '../../utils'; | ||
import { getAggBlockITC } from './AggBlock'; | ||
|
||
import { getAvgITC } from './Metrics/Avg'; | ||
import { getCardinalityITC } from './Metrics/Cardinality'; | ||
import { getExtendedStatsITC } from './Metrics/ExtendedStats'; | ||
|
||
export function getAggRulesITC(opts: mixed = {}): InputTypeComposer { | ||
const name = getTypeName('AggRules', opts); | ||
const description = desc( | ||
` | ||
The aggregations framework helps provide aggregated data based on | ||
a search query. It is based on simple building blocks called aggregations, | ||
that can be composed in order to build complex summaries of the data. | ||
[Documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html) | ||
` | ||
); | ||
|
||
return getOrSetType(name, () => | ||
// $FlowFixMe | ||
InputTypeComposer.create({ | ||
name, | ||
description, | ||
fields: { | ||
avg: () => getAvgITC(opts), | ||
cardinality: () => getCardinalityITC(opts), | ||
extended_stats: () => getExtendedStatsITC(opts), | ||
|
||
aggs: { | ||
type: () => [getAggBlockITC(opts)], | ||
description: 'Aggregation block', | ||
}, | ||
}, | ||
})); | ||
} |
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,29 @@ | ||
/* @flow */ | ||
|
||
import { InputTypeComposer } from 'graphql-compose'; | ||
import { getTypeName, getOrSetType, desc } from '../../../utils'; | ||
import { getCommonsScriptITC } from '../../Commons/Script'; | ||
|
||
export function getAvgITC(opts: mixed = {}): InputTypeComposer { | ||
const name = getTypeName('AggsAvg', opts); | ||
const description = desc(` | ||
A single-value metrics aggregation that computes the average | ||
of numeric values that are extracted from the aggregated documents. | ||
These values can be extracted either from specific numeric fields | ||
in the documents, or be generated by a provided script. | ||
[Documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-avg-aggregation.html) | ||
`); | ||
|
||
return getOrSetType(name, () => | ||
// $FlowFixMe | ||
InputTypeComposer.create({ | ||
name, | ||
description, | ||
fields: { | ||
field: 'String', | ||
missing: 'Float', | ||
script: () => getCommonsScriptITC(), | ||
}, | ||
}) | ||
); | ||
} |
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,39 @@ | ||
/* @flow */ | ||
|
||
import { InputTypeComposer } from 'graphql-compose'; | ||
import { getTypeName, getOrSetType, desc } from '../../../utils'; | ||
import { getCommonsScriptITC } from '../../Commons/Script'; | ||
|
||
export function getCardinalityITC(opts: mixed = {}): InputTypeComposer { | ||
const name = getTypeName('AggsCardinality', opts); | ||
const description = desc( | ||
` | ||
A single-value metrics aggregation that calculates an approximate count | ||
of distinct values. Values can be extracted either from specific fields | ||
in the document or generated by a script. | ||
[Documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.html) | ||
` | ||
); | ||
|
||
return getOrSetType(name, () => | ||
// $FlowFixMe | ||
InputTypeComposer.create({ | ||
name, | ||
description, | ||
fields: { | ||
field: 'String', | ||
precision_threshold: { | ||
type: 'Int', | ||
defaultValue: 3000, | ||
description: desc( | ||
` | ||
Allows to trade memory for accuracy, and defines a unique count | ||
below which counts are expected to be close to accurate. | ||
` | ||
), | ||
}, | ||
missing: 'String', | ||
script: () => getCommonsScriptITC(), | ||
}, | ||
})); | ||
} |
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,31 @@ | ||
/* @flow */ | ||
|
||
import { InputTypeComposer } from 'graphql-compose'; | ||
import { getTypeName, getOrSetType, desc } from '../../../utils'; | ||
import { getCommonsScriptITC } from '../../Commons/Script'; | ||
|
||
export function getExtendedStatsITC(opts: mixed = {}): InputTypeComposer { | ||
const name = getTypeName('AggsExtendedStats', opts); | ||
const description = desc( | ||
` | ||
A multi-value metrics aggregation that computes stats over numeric values | ||
extracted from the aggregated documents. These values can be extracted | ||
either from specific numeric fields in the documents, or be generated | ||
by a provided script. | ||
[Documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-extendedstats-aggregation.html) | ||
` | ||
); | ||
|
||
return getOrSetType(name, () => | ||
// $FlowFixMe | ||
InputTypeComposer.create({ | ||
name, | ||
description, | ||
fields: { | ||
field: 'String', | ||
sigma: 'Float', | ||
missing: 'Float', | ||
script: () => getCommonsScriptITC(), | ||
}, | ||
})); | ||
} |
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,52 @@ | ||
import argsBlockConverter, { | ||
convertAggsBlocks, | ||
convertAggsRules, | ||
} from '../converter'; | ||
|
||
describe('AGGS args converter', () => { | ||
it('convertAggsRules()', () => { | ||
expect(convertAggsRules({ some: { field: 1 } })).toEqual({ | ||
some: { field: 1 }, | ||
}); | ||
}); | ||
|
||
it('convertAggsBlocks()', () => { | ||
expect( | ||
convertAggsBlocks([ | ||
{ key: 'field1', value: {} }, | ||
{ key: 'field2', value: {} }, | ||
]) | ||
).toEqual({ | ||
field1: {}, | ||
field2: {}, | ||
}); | ||
}); | ||
|
||
it('should convert recursively aggs', () => { | ||
expect( | ||
convertAggsBlocks([ | ||
{ key: 'field1', value: { aggs: [{ key: 'field2', value: {} }] } }, | ||
]) | ||
).toEqual({ field1: { aggs: { field2: {} } } }); | ||
}); | ||
|
||
it('argsBlockConverter()', () => { | ||
expect.assertions(4); | ||
const mockResolve = (source, args, context, info) => { | ||
expect(args.body.aggs).toEqual({ | ||
field1: {}, | ||
field2: {}, | ||
}); | ||
expect(source).toEqual('source'); | ||
expect(context).toEqual('context'); | ||
expect(info).toEqual('info'); | ||
}; | ||
|
||
const args = { | ||
body: { | ||
aggs: [{ key: 'field1', value: {} }, { key: 'field2', value: {} }], | ||
}, | ||
}; | ||
argsBlockConverter(mockResolve)('source', args, 'context', 'info'); | ||
}); | ||
}); |
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,55 @@ | ||
import type { GraphQLFieldResolver } from 'graphql/type/definition'; | ||
|
||
export type ElasticAggsT = { | ||
[outputFieldName: string]: ElasticAggsRulesT, | ||
}; | ||
|
||
export type ElasticAggsRulesT = { | ||
[aggOperationName: string]: mixed, | ||
aggs: ElasticAggsT, | ||
}; | ||
|
||
export type GqlAggBlock = { | ||
key: string, | ||
value: GqlAggRules, | ||
}; | ||
|
||
export type GqlAggRules = { | ||
[aggOperationName: string]: mixed, | ||
aggs: GqlAggBlock, | ||
}; | ||
|
||
export default function argsBlockConverter( | ||
resolve: GraphQLFieldResolver<*, *> | ||
): GraphQLFieldResolver<*, *> { | ||
return (source, args, context, info) => { | ||
if (args.body && Array.isArray(args.body.aggs)) { | ||
const aggs: GqlAggBlock[] = args.body.aggs; | ||
args.body.aggs = convertAggsBlocks(aggs); // eslint-disable-line | ||
} | ||
|
||
return resolve(source, args, context, info); | ||
}; | ||
} | ||
|
||
export function convertAggsBlocks(blockList: GqlAggBlock[]): ElasticAggsT { | ||
const result = {}; | ||
blockList.forEach(block => { | ||
if (block.key && block.value) { | ||
result[block.key] = convertAggsRules(block.value); | ||
} | ||
}); | ||
return result; | ||
} | ||
|
||
export function convertAggsRules(rules: GqlAggRules): ElasticAggsRulesT { | ||
const result = {}; | ||
Object.keys(rules).forEach(key => { | ||
if (key === 'aggs' && rules.aggs) { | ||
result.aggs = convertAggsBlocks(rules.aggs); | ||
} else { | ||
result[key] = rules[key]; | ||
} | ||
}); | ||
return result; | ||
} |
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