[data.search.aggs] Remove fieldFormats from AggConfig & AggConfigs (#69762)

This commit is contained in:
Luke Elmers 2020-06-29 10:10:34 -06:00 committed by GitHub
parent 462bf1520f
commit 851e7ff9b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
66 changed files with 203 additions and 578 deletions

View file

@ -17,7 +17,8 @@
* under the License.
*/
import { IFieldFormatsRegistry } from '.';
import { identity } from 'lodash';
import { FieldFormat, IFieldFormatsRegistry } from '.';
export const fieldFormatsMock: IFieldFormatsRegistry = {
getByFieldType: jest.fn(),
@ -35,6 +36,9 @@ export const fieldFormatsMock: IFieldFormatsRegistry = {
init: jest.fn(),
register: jest.fn(),
parseDefaultTypeMap: jest.fn(),
deserialize: jest.fn(),
deserialize: jest.fn().mockImplementation(() => {
const DefaultFieldFormat = FieldFormat.from(identity);
return new DefaultFieldFormat();
}),
getTypeWithoutMetaParams: jest.fn(),
};

View file

@ -184,10 +184,7 @@ export class DataPublicPlugin implements Plugin<DataPublicPluginSetup, DataPubli
const query = this.queryService.start(savedObjects);
setQueryService(query);
const search = this.searchService.start(core, {
indexPatterns,
fieldFormats,
});
const search = this.searchService.start(core, { indexPatterns });
setSearchService(search);
uiActions.addTriggerAction(

View file

@ -25,31 +25,23 @@ import { AggType } from './agg_type';
import { AggTypesRegistryStart } from './agg_types_registry';
import { mockDataServices, mockAggTypesRegistry } from './test_helpers';
import { MetricAggType } from './metrics/metric_agg_type';
import {
Field as IndexPatternField,
IndexPattern,
IIndexPatternFieldList,
} from '../../index_patterns';
import { IndexPattern, IIndexPatternFieldList } from '../../index_patterns';
import { stubIndexPatternWithFields } from '../../../public/stubs';
import { FieldFormatsStart } from '../../field_formats';
import { fieldFormatsServiceMock } from '../../field_formats/mocks';
describe('AggConfig', () => {
let indexPattern: IndexPattern;
let typesRegistry: AggTypesRegistryStart;
let fieldFormats: FieldFormatsStart;
beforeEach(() => {
jest.restoreAllMocks();
mockDataServices();
fieldFormats = fieldFormatsServiceMock.createStartContract();
indexPattern = stubIndexPatternWithFields as IndexPattern;
typesRegistry = mockAggTypesRegistry();
});
describe('#toDsl', () => {
it('calls #write()', () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, [], { typesRegistry });
const configStates = {
enabled: true,
type: 'date_histogram',
@ -64,7 +56,7 @@ describe('AggConfig', () => {
});
it('uses the type name as the agg name', () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, [], { typesRegistry });
const configStates = {
enabled: true,
type: 'date_histogram',
@ -79,7 +71,7 @@ describe('AggConfig', () => {
});
it('uses the params from #write() output as the agg params', () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, [], { typesRegistry });
const configStates = {
enabled: true,
type: 'date_histogram',
@ -109,7 +101,7 @@ describe('AggConfig', () => {
params: {},
},
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
const histoConfig = ac.byName('date_histogram')[0];
const avgConfig = ac.byName('avg')[0];
@ -219,8 +211,8 @@ describe('AggConfig', () => {
testsIdentical.forEach((configState, index) => {
it(`identical aggregations (${index})`, () => {
const ac1 = new AggConfigs(indexPattern, configState, { typesRegistry, fieldFormats });
const ac2 = new AggConfigs(indexPattern, configState, { typesRegistry, fieldFormats });
const ac1 = new AggConfigs(indexPattern, configState, { typesRegistry });
const ac2 = new AggConfigs(indexPattern, configState, { typesRegistry });
expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true);
});
});
@ -260,8 +252,8 @@ describe('AggConfig', () => {
testsIdenticalDifferentOrder.forEach((test, index) => {
it(`identical aggregations (${index}) - init json is in different order`, () => {
const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry, fieldFormats });
const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry, fieldFormats });
const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry });
const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry });
expect(ac1.jsonDataEquals(ac2.aggs)).toBe(true);
});
});
@ -325,8 +317,8 @@ describe('AggConfig', () => {
testsDifferent.forEach((test, index) => {
it(`different aggregations (${index})`, () => {
const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry, fieldFormats });
const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry, fieldFormats });
const ac1 = new AggConfigs(indexPattern, test.config1, { typesRegistry });
const ac2 = new AggConfigs(indexPattern, test.config2, { typesRegistry });
expect(ac1.jsonDataEquals(ac2.aggs)).toBe(false);
});
});
@ -334,7 +326,7 @@ describe('AggConfig', () => {
describe('#serialize', () => {
it('includes the aggs id, params, type and schema', () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, [], { typesRegistry });
const configStates = {
enabled: true,
type: 'date_histogram',
@ -365,8 +357,8 @@ describe('AggConfig', () => {
params: {},
},
];
const ac1 = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac2 = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac1 = new AggConfigs(indexPattern, configStates, { typesRegistry });
const ac2 = new AggConfigs(indexPattern, configStates, { typesRegistry });
// this relies on the assumption that js-engines consistently loop over properties in insertion order.
// most likely the case, but strictly speaking not guaranteed by the JS and JSON specifications.
@ -394,7 +386,7 @@ describe('AggConfig', () => {
params: { field: 'machine.os.keyword' },
},
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
expect(ac.aggs.map((agg) => agg.toSerializedFieldFormat())).toMatchInlineSnapshot(`
Array [
@ -456,7 +448,7 @@ describe('AggConfig', () => {
},
},
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
expect(ac.aggs.map((agg) => agg.toSerializedFieldFormat())).toMatchInlineSnapshot(`
Array [
@ -478,20 +470,8 @@ describe('AggConfig', () => {
});
describe('#toExpressionAst', () => {
beforeEach(() => {
fieldFormats.getDefaultInstance = (() => ({
getConverterFor: (t?: string) => t || identity,
})) as any;
indexPattern.fields.getByName = (name) =>
({
format: {
getConverterFor: (t?: string) => t || identity,
},
} as IndexPatternField);
});
it('works with primitive param types', () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, [], { typesRegistry });
const configStates = {
enabled: true,
type: 'terms',
@ -540,7 +520,7 @@ describe('AggConfig', () => {
});
it('creates a subexpression for params of type "agg"', () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, [], { typesRegistry });
const configStates = {
type: 'terms',
params: {
@ -616,7 +596,7 @@ describe('AggConfig', () => {
},
});
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, [], { typesRegistry });
const configStates = {
type: 'range',
params: {
@ -647,7 +627,7 @@ describe('AggConfig', () => {
});
it('stringifies any other params which are an object', () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, [], { typesRegistry });
const configStates = {
type: 'terms',
params: {
@ -662,7 +642,7 @@ describe('AggConfig', () => {
});
it(`returns undefined if an expressionName doesn't exist on the agg type`, () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, [], { typesRegistry });
const configStates = {
type: 'unknown type',
params: {},
@ -676,7 +656,7 @@ describe('AggConfig', () => {
let aggConfig: AggConfig;
beforeEach(() => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, [], { typesRegistry });
aggConfig = ac.createAggConfig({ type: 'count' } as CreateAggConfigParams);
});
@ -702,85 +682,4 @@ describe('AggConfig', () => {
expect(label).toBe('');
});
});
describe('#fieldFormatter - custom getFormat handler', () => {
it('returns formatter from getFormat handler', () => {
const ac = new AggConfigs(indexPattern, [], { typesRegistry, fieldFormats });
const configStates = {
enabled: true,
type: 'count',
schema: 'metric',
params: { field: '@timestamp' },
};
const aggConfig = ac.createAggConfig(configStates);
const fieldFormatter = aggConfig.fieldFormatter();
expect(fieldFormatter).toBeDefined();
expect(fieldFormatter('text')).toBe('text');
});
});
// TODO: Converting these field formatter tests from browser tests to unit
// tests makes them much less helpful due to the extensive use of mocking.
// We should revisit these and rewrite them into something more useful.
describe('#fieldFormatter - no custom getFormat handler', () => {
let aggConfig: AggConfig;
beforeEach(() => {
fieldFormats.getDefaultInstance = (() => ({
getConverterFor: (t?: string) => t || identity,
})) as any;
indexPattern.fields.getByName = (name) =>
({
format: {
getConverterFor: (t?: string) => t || identity,
},
} as IndexPatternField);
const configStates = {
enabled: true,
type: 'histogram',
schema: 'bucket',
params: {
field: 'bytes',
},
};
const ac = new AggConfigs(indexPattern, [configStates], { typesRegistry, fieldFormats });
aggConfig = ac.createAggConfig(configStates);
});
it("returns the field's formatter", () => {
aggConfig.params.field = {
format: {
getConverterFor: (t?: string) => t || identity,
},
};
expect(aggConfig.fieldFormatter().toString()).toBe(
aggConfig.getField().format.getConverterFor().toString()
);
});
it('returns the string format if the field does not have a format', () => {
const agg = aggConfig;
agg.params.field = { type: 'number', format: null };
const fieldFormatter = agg.fieldFormatter();
expect(fieldFormatter).toBeDefined();
expect(fieldFormatter('text')).toBe('text');
});
it('returns the string format if there is no field', () => {
const agg = aggConfig;
delete agg.params.field;
const fieldFormatter = agg.fieldFormatter();
expect(fieldFormatter).toBeDefined();
expect(fieldFormatter('text')).toBe('text');
});
it('returns the html converter if "html" is passed in', () => {
const field = indexPattern.fields.getByName('bytes');
expect(aggConfig.fieldFormatter('html').toString()).toBe(
field!.format.getConverterFor('html').toString()
);
});
});
});

View file

@ -30,8 +30,6 @@ import { writeParams } from './agg_params';
import { IAggConfigs } from './agg_configs';
import { FetchOptions } from '../fetch';
import { ISearchSource } from '../search_source';
import { FieldFormatsContentType, KBN_FIELD_TYPES } from '../../../common';
import { FieldFormatsStart } from '../../field_formats';
type State = string | number | boolean | null | undefined | SerializableState;
@ -52,10 +50,6 @@ export type AggConfigSerialized = Ensure<
SerializableState
>;
export interface AggConfigDependencies {
fieldFormats: FieldFormatsStart;
}
export type AggConfigOptions = Assign<AggConfigSerialized, { type: IAggType }>;
/**
@ -116,13 +110,8 @@ export class AggConfig {
private __type: IAggType;
private __typeDecorations: any;
private subAggs: AggConfig[] = [];
private readonly fieldFormats: FieldFormatsStart;
constructor(
aggConfigs: IAggConfigs,
opts: AggConfigOptions,
{ fieldFormats }: AggConfigDependencies
) {
constructor(aggConfigs: IAggConfigs, opts: AggConfigOptions) {
this.aggConfigs = aggConfigs;
this.id = String(opts.id || AggConfig.nextId(aggConfigs.aggs as any));
this.enabled = typeof opts.enabled === 'boolean' ? opts.enabled : true;
@ -143,8 +132,6 @@ export class AggConfig {
// @ts-ignore
this.__type = this.__type;
this.fieldFormats = fieldFormats;
}
/**
@ -433,24 +420,6 @@ export class AggConfig {
return this.aggConfigs.timeRange;
}
fieldFormatter(contentType?: FieldFormatsContentType, defaultFormat?: any) {
const format = this.type && this.type.getFormat(this);
if (format) {
return format.getConverterFor(contentType);
}
return this.fieldOwnFormatter(contentType, defaultFormat);
}
fieldOwnFormatter(contentType?: FieldFormatsContentType, defaultFormat?: any) {
const field = this.getField();
let format = field && field.format;
if (!format) format = defaultFormat;
if (!format) format = this.fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING);
return format.getConverterFor(contentType);
}
fieldName() {
const field = this.getField();
return field ? field.name : '';

View file

@ -24,12 +24,10 @@ import { AggTypesRegistryStart } from './agg_types_registry';
import { mockDataServices, mockAggTypesRegistry } from './test_helpers';
import { Field as IndexPatternField, IndexPattern } from '../../index_patterns';
import { stubIndexPattern, stubIndexPatternWithFields } from '../../../public/stubs';
import { fieldFormatsServiceMock } from '../../field_formats/mocks';
describe('AggConfigs', () => {
let indexPattern: IndexPattern;
let typesRegistry: AggTypesRegistryStart;
const fieldFormats = fieldFormatsServiceMock.createStartContract();
beforeEach(() => {
mockDataServices();
@ -47,7 +45,7 @@ describe('AggConfigs', () => {
},
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
expect(ac.aggs).toHaveLength(1);
});
@ -72,7 +70,7 @@ describe('AggConfigs', () => {
];
const spy = jest.spyOn(AggConfig, 'ensureIds');
new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
new AggConfigs(indexPattern, configStates, { typesRegistry });
expect(spy).toHaveBeenCalledTimes(1);
expect(spy.mock.calls[0]).toEqual([configStates]);
spy.mockRestore();
@ -94,20 +92,16 @@ describe('AggConfigs', () => {
},
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
expect(ac.aggs).toHaveLength(2);
ac.createAggConfig(
new AggConfig(
ac,
{
enabled: true,
type: typesRegistry.get('terms'),
params: {},
schema: 'split',
},
{ fieldFormats }
)
new AggConfig(ac, {
enabled: true,
type: typesRegistry.get('terms'),
params: {},
schema: 'split',
})
);
expect(ac.aggs).toHaveLength(3);
});
@ -121,7 +115,7 @@ describe('AggConfigs', () => {
},
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
expect(ac.aggs).toHaveLength(1);
ac.createAggConfig({
@ -142,7 +136,7 @@ describe('AggConfigs', () => {
},
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
expect(ac.aggs).toHaveLength(1);
ac.createAggConfig(
@ -170,7 +164,7 @@ describe('AggConfigs', () => {
{ type: 'percentiles', enabled: true, params: {}, schema: 'metric' },
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
const sorted = ac.getRequestAggs();
const aggs = indexBy(ac.aggs, (agg) => agg.type.name);
@ -193,7 +187,7 @@ describe('AggConfigs', () => {
{ type: 'count', enabled: true, params: {}, schema: 'metric' },
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
const sorted = ac.getResponseAggs();
const aggs = indexBy(ac.aggs, (agg) => agg.type.name);
@ -210,7 +204,7 @@ describe('AggConfigs', () => {
{ type: 'percentiles', enabled: true, params: { percents: [1, 2, 3] }, schema: 'metric' },
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
const sorted = ac.getResponseAggs();
const aggs = indexBy(ac.aggs, (agg) => agg.type.name);
@ -231,7 +225,7 @@ describe('AggConfigs', () => {
it('uses the sorted aggs', () => {
const configStates = [{ enabled: true, type: 'avg', params: { field: 'bytes' } }];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
const spy = jest.spyOn(AggConfigs.prototype, 'getRequestAggs');
ac.toDsl();
expect(spy).toHaveBeenCalledTimes(1);
@ -245,10 +239,7 @@ describe('AggConfigs', () => {
{ enabled: true, type: 'count', params: {} },
];
const ac = new AggConfigs(indexPattern, configStates, {
typesRegistry,
fieldFormats,
});
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
const aggInfos = ac.aggs.map((aggConfig) => {
const football = {};
@ -291,7 +282,7 @@ describe('AggConfigs', () => {
},
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
const dsl = ac.toDsl();
const histo = ac.byName('date_histogram')[0];
const count = ac.byName('count')[0];
@ -316,10 +307,7 @@ describe('AggConfigs', () => {
{ enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } },
];
const ac = new AggConfigs(indexPattern, configStates, {
typesRegistry,
fieldFormats,
});
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
const dsl = ac.toDsl();
const histo = ac.byName('date_histogram')[0];
const metrics = ac.bySchemaName('metrics');
@ -344,7 +332,7 @@ describe('AggConfigs', () => {
{ enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } },
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
const topLevelDsl = ac.toDsl(true);
const buckets = ac.bySchemaName('buckets');
const metrics = ac.bySchemaName('metrics');
@ -414,7 +402,7 @@ describe('AggConfigs', () => {
},
];
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry, fieldFormats });
const ac = new AggConfigs(indexPattern, configStates, { typesRegistry });
const topLevelDsl = ac.toDsl(true)['2'];
expect(Object.keys(topLevelDsl.aggs)).toContain('1');

View file

@ -28,7 +28,6 @@ import { IndexPattern } from '../../index_patterns';
import { ISearchSource } from '../search_source';
import { FetchOptions } from '../fetch';
import { TimeRange } from '../../../common';
import { FieldFormatsStart } from '../../field_formats';
function removeParentAggs(obj: any) {
for (const prop in obj) {
@ -48,7 +47,6 @@ function parseParentAggs(dslLvlCursor: any, dsl: any) {
export interface AggConfigsOptions {
typesRegistry: AggTypesRegistryStart;
fieldFormats: FieldFormatsStart;
}
export type CreateAggConfigParams = Assign<AggConfigSerialized, { type: string | IAggType }>;
@ -70,7 +68,6 @@ export type IAggConfigs = AggConfigs;
export class AggConfigs {
public indexPattern: IndexPattern;
public timeRange?: TimeRange;
private readonly fieldFormats: FieldFormatsStart;
private readonly typesRegistry: AggTypesRegistryStart;
aggs: IAggConfig[];
@ -86,7 +83,6 @@ export class AggConfigs {
this.aggs = [];
this.indexPattern = indexPattern;
this.fieldFormats = opts.fieldFormats;
configStates.forEach((params: any) => this.createAggConfig(params));
}
@ -117,7 +113,6 @@ export class AggConfigs {
const aggConfigs = new AggConfigs(this.indexPattern, this.aggs.filter(filterAggs), {
typesRegistry: this.typesRegistry,
fieldFormats: this.fieldFormats,
});
return aggConfigs;
@ -134,14 +129,10 @@ export class AggConfigs {
aggConfig = params;
params.parent = this;
} else {
aggConfig = new AggConfig(
this,
{
...params,
type: typeof type === 'string' ? this.typesRegistry.get(type) : type,
},
{ fieldFormats: this.fieldFormats }
);
aggConfig = new AggConfig(this, {
...params,
type: typeof type === 'string' ? this.typesRegistry.get(type) : type,
});
}
if (addToAggConfigs) {

View file

@ -159,47 +159,6 @@ describe('AggType Class', () => {
});
});
describe('getFormat', function () {
let aggConfig: IAggConfig;
let field: any;
beforeEach(() => {
aggConfig = ({
getField: jest.fn(() => field),
} as unknown) as IAggConfig;
});
test('returns the formatter for the aggConfig', () => {
const aggType = new AggType(
{
name: 'name',
title: 'title',
},
dependencies
);
field = {
format: 'format',
};
expect(aggType.getFormat(aggConfig)).toBe('format');
});
test('returns default formatter', () => {
const aggType = new AggType(
{
name: 'name',
title: 'title',
},
dependencies
);
field = undefined;
expect(aggType.getFormat(aggConfig)).toBe('default');
});
});
describe('getSerializedFormat', () => {
test('returns the default serialized field format if it exists', () => {
const aggConfig = ({

View file

@ -28,7 +28,6 @@ import { IAggConfigs } from './agg_configs';
import { Adapters } from '../../../../../plugins/inspector/public';
import { BaseParamType } from './param_types/base';
import { AggParamType } from './param_types/agg';
import { KBN_FIELD_TYPES, IFieldFormat } from '../../../common';
import { ISearchSource } from '../search_source';
import { GetInternalStartServicesFn } from '../../types';
@ -58,7 +57,6 @@ export interface AggTypeConfig<
inspectorAdapters: Adapters,
abortSignal?: AbortSignal
) => Promise<any>;
getFormat?: (agg: TAggConfig) => IFieldFormat;
getSerializedFormat?: (agg: TAggConfig) => SerializedFieldFormat;
getValue?: (agg: TAggConfig, bucket: any) => any;
getKey?: (bucket: any, key: any, agg: TAggConfig) => any;
@ -197,16 +195,6 @@ export class AggType<
inspectorAdapters: Adapters,
abortSignal?: AbortSignal
) => Promise<any>;
/**
* Pick a format for the values produced by this agg type,
* overridden by several metrics that always output a simple
* number
*
* @param {agg} agg - the agg to pick a format for
* @return {FieldFormat}
*/
getFormat: (agg: TAggConfig) => IFieldFormat;
/**
* Get the serialized format for the values produced by this agg type,
* overridden by several metrics that always output a simple number.
@ -283,15 +271,6 @@ export class AggType<
this.decorateAggConfig = config.decorateAggConfig || (() => ({}));
this.postFlightRequest = config.postFlightRequest || identity;
this.getFormat =
config.getFormat ||
((agg: TAggConfig) => {
const field = agg.getField();
const { fieldFormats } = getInternalStartServices();
return field ? field.format : fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.STRING);
});
this.getSerializedFormat =
config.getSerializedFormat ||
((agg: TAggConfig) => {

View file

@ -26,7 +26,6 @@ import { AggConfigs, CreateAggConfigParams } from '../agg_configs';
import { BUCKET_TYPES } from './bucket_agg_types';
import { IBucketAggConfig } from './bucket_agg_type';
import { mockAggTypesRegistry } from '../test_helpers';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
const indexPattern = {
id: '1234',
@ -220,10 +219,9 @@ const nestedOtherResponse = {
describe('Terms Agg Other bucket helper', () => {
const typesRegistry = mockAggTypesRegistry();
const fieldFormats = fieldFormatsServiceMock.createStartContract();
const getAggConfigs = (aggs: CreateAggConfigParams[] = []) => {
return new AggConfigs(indexPattern, [...aggs], { typesRegistry, fieldFormats });
return new AggConfigs(indexPattern, [...aggs], { typesRegistry });
};
describe('buildOtherBucketAgg', () => {

View file

@ -82,7 +82,6 @@ describe('AggConfig Filters', () => {
],
{
typesRegistry: mockAggTypesRegistry([getDateHistogramBucketAgg(aggTypesDependencies)]),
fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats,
}
);
const bucketKey = 1422579600000;

View file

@ -76,7 +76,6 @@ describe('AggConfig Filters', () => {
],
{
typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]),
fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats,
}
);
};

View file

@ -73,7 +73,6 @@ describe('AggConfig Filters', () => {
],
{
typesRegistry: mockAggTypesRegistry([getFiltersBucketAgg(aggTypesDependencies)]),
fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats,
}
);
};

View file

@ -23,12 +23,21 @@ import { mockAggTypesRegistry } from '../../test_helpers';
import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../bucket_agg_type';
import { BytesFormat, FieldFormatsGetConfigFn } from '../../../../../common';
import { GetInternalStartServicesFn, InternalStartServices } from '../../../../types';
import { FieldFormatsStart } from '../../../../field_formats';
import { fieldFormatsServiceMock } from '../../../../field_formats/mocks';
describe('AggConfig Filters', () => {
let getInternalStartServices: GetInternalStartServicesFn;
let fieldFormats: FieldFormatsStart;
beforeEach(() => {
fieldFormats = fieldFormatsServiceMock.createStartContract();
getInternalStartServices = () => (({ fieldFormats } as unknown) as InternalStartServices);
});
describe('histogram', () => {
const getConfig = (() => {}) as FieldFormatsGetConfigFn;
const fieldFormats = fieldFormatsServiceMock.createStartContract();
const getAggConfigs = () => {
const field = {
name: 'bytes',
@ -57,21 +66,25 @@ describe('AggConfig Filters', () => {
},
},
],
{ typesRegistry: mockAggTypesRegistry(), fieldFormats }
{ typesRegistry: mockAggTypesRegistry() }
);
};
test('should return an range filter for histogram', () => {
const aggConfigs = getAggConfigs();
const filter = createFilterHistogram(aggConfigs.aggs[0] as IBucketAggConfig, '2048');
const filter = createFilterHistogram(getInternalStartServices)(
aggConfigs.aggs[0] as IBucketAggConfig,
'2048'
);
expect(fieldFormats.deserialize).toHaveBeenCalledTimes(1);
expect(filter).toHaveProperty('meta');
expect(filter.meta).toHaveProperty('index', '1234');
expect(filter).toHaveProperty('range');
expect(filter.range).toHaveProperty('bytes');
expect(filter.range.bytes).toHaveProperty('gte', 2048);
expect(filter.range.bytes).toHaveProperty('lt', 3072);
expect(filter.meta).toHaveProperty('formattedValue', '2,048');
expect(filter.meta).toHaveProperty('formattedValue');
});
});
});

View file

@ -19,15 +19,20 @@
import { IBucketAggConfig } from '../bucket_agg_type';
import { buildRangeFilter, RangeFilterParams } from '../../../../../common';
import { GetInternalStartServicesFn } from '../../../../types';
export const createFilterHistogram = (aggConfig: IBucketAggConfig, key: string) => {
const value = parseInt(key, 10);
const params: RangeFilterParams = { gte: value, lt: value + aggConfig.params.interval };
/** @internal */
export const createFilterHistogram = (getInternalStartServices: GetInternalStartServicesFn) => {
return (aggConfig: IBucketAggConfig, key: string) => {
const { fieldFormats } = getInternalStartServices();
const value = parseInt(key, 10);
const params: RangeFilterParams = { gte: value, lt: value + aggConfig.params.interval };
return buildRangeFilter(
aggConfig.params.field,
params,
aggConfig.getIndexPattern(),
aggConfig.fieldFormatter()(key)
);
return buildRangeFilter(
aggConfig.params.field,
params,
aggConfig.getIndexPattern(),
fieldFormats.deserialize(aggConfig.toSerializedFieldFormat()).convert(key)
);
};
};

View file

@ -55,7 +55,7 @@ describe('AggConfig Filters', () => {
},
} as any;
return new AggConfigs(indexPattern, aggs, { typesRegistry, fieldFormats });
return new AggConfigs(indexPattern, aggs, { typesRegistry });
};
test('should return a range filter for ip_range agg', () => {

View file

@ -24,19 +24,29 @@ import { AggConfigs } from '../../agg_configs';
import { mockDataServices, mockAggTypesRegistry } from '../../test_helpers';
import { BUCKET_TYPES } from '../bucket_agg_types';
import { IBucketAggConfig } from '../bucket_agg_type';
import { FieldFormatsStart } from '../../../../field_formats';
import { fieldFormatsServiceMock } from '../../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../core/public/mocks';
import { InternalStartServices } from '../../../../types';
import { GetInternalStartServicesFn, InternalStartServices } from '../../../../types';
describe('AggConfig Filters', () => {
describe('range', () => {
let aggTypesDependencies: RangeBucketAggDependencies;
let getInternalStartServices: GetInternalStartServicesFn;
let fieldFormats: FieldFormatsStart;
beforeEach(() => {
fieldFormats = fieldFormatsServiceMock.createStartContract();
getInternalStartServices = () =>
(({
fieldFormats,
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices);
aggTypesDependencies = {
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
@ -75,25 +85,28 @@ describe('AggConfig Filters', () => {
],
{
typesRegistry: mockAggTypesRegistry([getRangeBucketAgg(aggTypesDependencies)]),
fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats,
}
);
};
test('should return a range filter for range agg', () => {
const aggConfigs = getAggConfigs();
const filter = createFilterRange(aggConfigs.aggs[0] as IBucketAggConfig, {
gte: 1024,
lt: 2048.0,
});
const filter = createFilterRange(getInternalStartServices)(
aggConfigs.aggs[0] as IBucketAggConfig,
{
gte: 1024,
lt: 2048.0,
}
);
expect(fieldFormats.deserialize).toHaveBeenCalledTimes(1);
expect(filter).toHaveProperty('range');
expect(filter).toHaveProperty('meta');
expect(filter.meta).toHaveProperty('index', '1234');
expect(filter.range).toHaveProperty('bytes');
expect(filter.range.bytes).toHaveProperty('gte', 1024.0);
expect(filter.range.bytes).toHaveProperty('lt', 2048.0);
expect(filter.meta).toHaveProperty('formattedValue', '≥ 1,024 and < 2,048');
expect(filter.meta).toHaveProperty('formattedValue');
});
});
});

View file

@ -19,12 +19,17 @@
import { IBucketAggConfig } from '../bucket_agg_type';
import { buildRangeFilter } from '../../../../../common';
import { GetInternalStartServicesFn } from '../../../../types';
export const createFilterRange = (aggConfig: IBucketAggConfig, params: any) => {
return buildRangeFilter(
aggConfig.params.field,
params,
aggConfig.getIndexPattern(),
aggConfig.fieldFormatter()(params)
);
/** @internal */
export const createFilterRange = (getInternalStartServices: GetInternalStartServicesFn) => {
return (aggConfig: IBucketAggConfig, params: any) => {
const { fieldFormats } = getInternalStartServices();
return buildRangeFilter(
aggConfig.params.field,
params,
aggConfig.getIndexPattern(),
fieldFormats.deserialize(aggConfig.toSerializedFieldFormat()).convert(params)
);
};
};

View file

@ -60,7 +60,6 @@ describe('AggConfig Filters', () => {
return new AggConfigs(indexPattern, aggs, {
typesRegistry: mockAggTypesRegistry([getTermsBucketAgg(aggTypesDependencies)]),
fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats,
});
};

View file

@ -31,7 +31,7 @@ import { dateHistogramInterval, TimeRange } from '../../../../common';
import { writeParams } from '../agg_params';
import { isMetricAggType } from '../metrics/metric_agg_type';
import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES, UI_SETTINGS } from '../../../../common';
import { KBN_FIELD_TYPES, UI_SETTINGS } from '../../../../common';
import { TimefilterContract } from '../../../query';
import { QuerySetup } from '../../../query/query_service';
import { GetInternalStartServicesFn } from '../../../types';
@ -137,21 +137,6 @@ export const getDateHistogramBucketAgg = ({
} as any,
};
},
getFormat(agg) {
const { fieldFormats } = getInternalStartServices();
const DateFieldFormat = fieldFormats.getType(FIELD_FORMAT_IDS.DATE);
if (!DateFieldFormat) {
throw new Error('Unable to retrieve Date Field Format');
}
return new DateFieldFormat(
{
pattern: agg.buckets.getScaledDateFormat(),
},
(key: string) => uiSettings.get(key)
);
},
getSerializedFormat(agg) {
return {
id: 'date',

View file

@ -78,7 +78,6 @@ describe('date_range params', () => {
],
{
typesRegistry: mockAggTypesRegistry([getDateRangeBucketAgg(aggTypesDependencies)]),
fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats,
}
);
};

View file

@ -25,9 +25,9 @@ import { IUiSettingsClient } from 'src/core/public';
import { BUCKET_TYPES } from './bucket_agg_types';
import { BucketAggType, IBucketAggConfig } from './bucket_agg_type';
import { createFilterDateRange } from './create_filter/date_range';
import { convertDateRangeToString, DateRangeKey } from './lib/date_range';
import { DateRangeKey } from './lib/date_range';
import { KBN_FIELD_TYPES, FieldFormat, TEXT_CONTEXT_TYPE } from '../../../../common';
import { KBN_FIELD_TYPES } from '../../../../common';
import { GetInternalStartServicesFn } from '../../../types';
import { BaseAggParams } from '../types';
@ -58,18 +58,6 @@ export const getDateRangeBucketAgg = ({
getKey({ from, to }): DateRangeKey {
return { from, to };
},
getFormat(agg) {
const { fieldFormats } = getInternalStartServices();
const formatter = agg.fieldOwnFormatter(
TEXT_CONTEXT_TYPE,
fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.DATE)
);
const DateRangeFormat = FieldFormat.from(function (range: DateRangeKey) {
return convertDateRangeToString(range, formatter);
});
return new DateRangeFormat();
},
getSerializedFormat(agg) {
return {
id: 'date_range',

View file

@ -41,6 +41,7 @@ export const getFilterBucketAgg = ({ getInternalStartServices }: FilterBucketAgg
{
name: BUCKET_TYPES.FILTER,
title: filterTitle,
makeLabel: () => filterTitle,
params: [
{
name: 'geo_bounding_box',

View file

@ -71,7 +71,6 @@ describe('Filters Agg', () => {
],
{
typesRegistry: mockAggTypesRegistry([getFiltersBucketAgg(aggTypesDependencies)]),
fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats,
}
);
};

View file

@ -81,7 +81,6 @@ describe('Geohash Agg', () => {
],
{
typesRegistry: mockAggTypesRegistry(),
fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats,
}
);
};

View file

@ -54,6 +54,7 @@ export const getGeoHashBucketAgg = ({ getInternalStartServices }: GeoHashBucketA
{
name: BUCKET_TYPES.GEOHASH_GRID,
title: geohashGridTitle,
makeLabel: () => geohashGridTitle,
params: [
{
name: 'field',

View file

@ -74,7 +74,6 @@ describe('Histogram Agg', () => {
],
{
typesRegistry: mockAggTypesRegistry([getHistogramBucketAgg(aggTypesDependencies)]),
fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats,
}
);
};

View file

@ -67,7 +67,7 @@ export const getHistogramBucketAgg = ({
makeLabel(aggConfig) {
return aggConfig.getFieldDisplayName();
},
createFilter: createFilterHistogram,
createFilter: createFilterHistogram(getInternalStartServices),
decorateAggConfig() {
let autoBounds: AutoBounds;

View file

@ -23,13 +23,8 @@ import { BucketAggType } from './bucket_agg_type';
import { BUCKET_TYPES } from './bucket_agg_types';
import { createFilterIpRange } from './create_filter/ip_range';
import {
convertIPRangeToString,
IpRangeKey,
RangeIpRangeAggKey,
CidrMaskIpRangeAggKey,
} from './lib/ip_range';
import { KBN_FIELD_TYPES, FieldFormat, TEXT_CONTEXT_TYPE } from '../../../../common';
import { IpRangeKey, RangeIpRangeAggKey, CidrMaskIpRangeAggKey } from './lib/ip_range';
import { KBN_FIELD_TYPES } from '../../../../common';
import { GetInternalStartServicesFn } from '../../../types';
import { BaseAggParams } from '../types';
@ -67,17 +62,6 @@ export const getIpRangeBucketAgg = ({ getInternalStartServices }: IpRangeBucketA
}
return { type: 'range', from: bucket.from, to: bucket.to };
},
getFormat(agg) {
const { fieldFormats } = getInternalStartServices();
const formatter = agg.fieldOwnFormatter(
TEXT_CONTEXT_TYPE,
fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.IP)
);
const IpRangeFormat = FieldFormat.from(function (range: IpRangeKey) {
return convertIPRangeToString(range, formatter);
});
return new IpRangeFormat();
},
getSerializedFormat(agg) {
return {
id: 'ip_range',

View file

@ -22,30 +22,9 @@ import { AggConfigs } from '../agg_configs';
import { mockDataServices, mockAggTypesRegistry } from '../test_helpers';
import { BUCKET_TYPES } from './bucket_agg_types';
import { FieldFormatsGetConfigFn, NumberFormat } from '../../../../common';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
import { InternalStartServices } from '../../../types';
const buckets = [
{
to: 1024,
to_as_string: '1024.0',
doc_count: 20904,
},
{
from: 1024,
from_as_string: '1024.0',
to: 2560,
to_as_string: '2560.0',
doc_count: 23358,
},
{
from: 2560,
from_as_string: '2560.0',
doc_count: 174250,
},
];
describe('Range Agg', () => {
let aggTypesDependencies: RangeBucketAggDependencies;
@ -53,7 +32,6 @@ describe('Range Agg', () => {
aggTypesDependencies = {
getInternalStartServices: () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices),
};
@ -99,23 +77,10 @@ describe('Range Agg', () => {
],
{
typesRegistry: mockAggTypesRegistry([getRangeBucketAgg(aggTypesDependencies)]),
fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats,
}
);
};
describe('formatting', () => {
test('formats bucket keys properly', () => {
const aggConfigs = getAggConfigs();
const agg = aggConfigs.aggs[0];
const format = (val: any) => agg.fieldFormatter()(agg.getKey(val));
expect(format(buckets[0])).toBe('≥ -∞ and < 1 KB');
expect(format(buckets[1])).toBe('≥ 1 KB and < 2.5 KB');
expect(format(buckets[2])).toBe('≥ 2.5 KB and < +∞');
});
});
describe('getSerializedFormat', () => {
test('generates a serialized field format in the expected shape', () => {
const aggConfigs = getAggConfigs();

View file

@ -19,16 +19,13 @@
import { i18n } from '@kbn/i18n';
import { BucketAggType } from './bucket_agg_type';
import { FieldFormat, KBN_FIELD_TYPES } from '../../../../common';
import { KBN_FIELD_TYPES } from '../../../../common';
import { RangeKey } from './range_key';
import { createFilterRange } from './create_filter/range';
import { BUCKET_TYPES } from './bucket_agg_types';
import { GetInternalStartServicesFn } from '../../../types';
import { BaseAggParams } from '../types';
const keyCaches = new WeakMap();
const formats = new WeakMap();
const rangeTitle = i18n.translate('data.search.aggs.buckets.rangeTitle', {
defaultMessage: 'Range',
});
@ -45,12 +42,14 @@ export interface AggParamsRange extends BaseAggParams {
}>;
}
export const getRangeBucketAgg = ({ getInternalStartServices }: RangeBucketAggDependencies) =>
new BucketAggType(
export const getRangeBucketAgg = ({ getInternalStartServices }: RangeBucketAggDependencies) => {
const keyCaches = new WeakMap();
return new BucketAggType(
{
name: BUCKET_TYPES.RANGE,
title: rangeTitle,
createFilter: createFilterRange,
createFilter: createFilterRange(getInternalStartServices),
makeLabel(aggConfig) {
return i18n.translate('data.search.aggs.aggTypesLabel', {
defaultMessage: '{fieldName} ranges',
@ -77,30 +76,6 @@ export const getRangeBucketAgg = ({ getInternalStartServices }: RangeBucketAggDe
return key;
},
getFormat(agg) {
let aggFormat = formats.get(agg);
if (aggFormat) return aggFormat;
const RangeFormat = FieldFormat.from((range: any) => {
const format = agg.fieldOwnFormatter();
const gte = '\u2265';
const lt = '\u003c';
return i18n.translate('data.search.aggs.aggTypes.rangesFormatMessage', {
defaultMessage: '{gte} {from} and {lt} {to}',
values: {
gte,
from: format(range.gte),
lt,
to: format(range.lt),
},
});
});
aggFormat = new RangeFormat();
formats.set(agg, aggFormat);
return aggFormat;
},
getSerializedFormat(agg) {
const format = agg.params.field ? agg.params.field.format.toJSON() : {};
return {
@ -132,3 +107,4 @@ export const getRangeBucketAgg = ({ getInternalStartServices }: RangeBucketAggDe
},
{ getInternalStartServices }
);
};

View file

@ -72,7 +72,6 @@ describe('Significant Terms Agg', () => {
typesRegistry: mockAggTypesRegistry([
getSignificantTermsBucketAgg(aggTypesDependencies),
]),
fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats,
}
);
};

View file

@ -20,11 +20,9 @@
import { AggConfigs } from '../agg_configs';
import { mockAggTypesRegistry } from '../test_helpers';
import { BUCKET_TYPES } from './bucket_agg_types';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
describe('Terms Agg', () => {
describe('order agg editor UI', () => {
const fieldFormats = fieldFormatsServiceMock.createStartContract();
const getAggConfigs = (params: Record<string, any> = {}) => {
const indexPattern = {
id: '1234',
@ -49,7 +47,7 @@ describe('Terms Agg', () => {
type: BUCKET_TYPES.TERMS,
},
],
{ typesRegistry: mockAggTypesRegistry(), fieldFormats }
{ typesRegistry: mockAggTypesRegistry() }
);
};

View file

@ -30,7 +30,7 @@ import { AggConfigSerialized, BaseAggParams, IAggConfigs } from '../types';
import { Adapters } from '../../../../../inspector/public';
import { ISearchSource } from '../../search_source';
import { IFieldFormat, FieldFormatsContentType, KBN_FIELD_TYPES } from '../../../../common';
import { KBN_FIELD_TYPES } from '../../../../common';
import { getRequestInspectorStats, getResponseInspectorStats } from '../../expressions';
import {
@ -88,22 +88,6 @@ export const getTermsBucketAgg = ({ getInternalStartServices }: TermsBucketAggDe
const params = agg.params;
return agg.getFieldDisplayName() + ': ' + params.order.text;
},
getFormat(bucket): IFieldFormat {
return {
getConverterFor: (type: FieldFormatsContentType) => {
return (val: any) => {
if (val === '__other__') {
return bucket.params.otherBucketLabel;
}
if (val === '__missing__') {
return bucket.params.missingBucketLabel;
}
return bucket.params.field.format.convert(val, type);
};
},
} as IFieldFormat;
},
getSerializedFormat(agg) {
const format = agg.params.field ? agg.params.field.format.toJSON() : {};
return {

View file

@ -46,7 +46,7 @@ const averageBucketTitle = i18n.translate('data.search.aggs.metrics.averageBucke
export const getBucketAvgMetricAgg = ({
getInternalStartServices,
}: BucketAvgMetricAggDependencies) => {
const { subtype, params, getFormat, getSerializedFormat } = siblingPipelineAggHelper;
const { subtype, params, getSerializedFormat } = siblingPipelineAggHelper;
return new MetricAggType(
{
@ -55,7 +55,6 @@ export const getBucketAvgMetricAgg = ({
makeLabel: (agg) => makeNestedLabel(agg, overallAverageLabel),
subtype,
params: [...params()],
getFormat,
getSerializedFormat,
getValue(agg, bucket) {
const customMetric = agg.getParam('customMetric');

View file

@ -45,7 +45,7 @@ const maxBucketTitle = i18n.translate('data.search.aggs.metrics.maxBucketTitle',
export const getBucketMaxMetricAgg = ({
getInternalStartServices,
}: BucketMaxMetricAggDependencies) => {
const { subtype, params, getFormat, getSerializedFormat } = siblingPipelineAggHelper;
const { subtype, params, getSerializedFormat } = siblingPipelineAggHelper;
return new MetricAggType(
{
@ -54,7 +54,6 @@ export const getBucketMaxMetricAgg = ({
makeLabel: (agg) => makeNestedLabel(agg, overallMaxLabel),
subtype,
params: [...params()],
getFormat,
getSerializedFormat,
},
{

View file

@ -45,7 +45,7 @@ const minBucketTitle = i18n.translate('data.search.aggs.metrics.minBucketTitle',
export const getBucketMinMetricAgg = ({
getInternalStartServices,
}: BucketMinMetricAggDependencies) => {
const { subtype, params, getFormat, getSerializedFormat } = siblingPipelineAggHelper;
const { subtype, params, getSerializedFormat } = siblingPipelineAggHelper;
return new MetricAggType(
{
@ -54,7 +54,6 @@ export const getBucketMinMetricAgg = ({
makeLabel: (agg) => makeNestedLabel(agg, overallMinLabel),
subtype,
params: [...params()],
getFormat,
getSerializedFormat,
},
{

View file

@ -45,7 +45,7 @@ const sumBucketTitle = i18n.translate('data.search.aggs.metrics.sumBucketTitle',
export const getBucketSumMetricAgg = ({
getInternalStartServices,
}: BucketSumMetricAggDependencies) => {
const { subtype, params, getFormat, getSerializedFormat } = siblingPipelineAggHelper;
const { subtype, params, getSerializedFormat } = siblingPipelineAggHelper;
return new MetricAggType(
{
@ -54,7 +54,6 @@ export const getBucketSumMetricAgg = ({
makeLabel: (agg) => makeNestedLabel(agg, overallSumLabel),
subtype,
params: [...params()],
getFormat,
getSerializedFormat,
},
{

View file

@ -49,11 +49,6 @@ export const getCardinalityMetricAgg = ({
values: { field: aggConfig.getFieldDisplayName() },
});
},
getFormat() {
const { fieldFormats } = getInternalStartServices();
return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
},
getSerializedFormat(agg) {
return {
id: 'number',

View file

@ -20,7 +20,6 @@
import { i18n } from '@kbn/i18n';
import { MetricAggType } from './metric_agg_type';
import { METRIC_TYPES } from './metric_agg_types';
import { KBN_FIELD_TYPES } from '../../../../common';
import { GetInternalStartServicesFn } from '../../../types';
export interface CountMetricAggDependencies {
@ -40,11 +39,6 @@ export const getCountMetricAgg = ({ getInternalStartServices }: CountMetricAggDe
defaultMessage: 'Count',
});
},
getFormat() {
const { fieldFormats } = getInternalStartServices();
return fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
},
getSerializedFormat(agg) {
return {
id: 'number',

View file

@ -46,7 +46,7 @@ const cumulativeSumTitle = i18n.translate('data.search.aggs.metrics.cumulativeSu
export const getCumulativeSumMetricAgg = ({
getInternalStartServices,
}: CumulativeSumMetricAggDependencies) => {
const { subtype, params, getFormat, getSerializedFormat } = parentPipelineAggHelper;
const { subtype, params, getSerializedFormat } = parentPipelineAggHelper;
return new MetricAggType(
{
@ -55,7 +55,6 @@ export const getCumulativeSumMetricAgg = ({
makeLabel: (agg) => makeNestedLabel(agg, cumulativeSumLabel),
subtype,
params: [...params()],
getFormat,
getSerializedFormat,
},
{

View file

@ -46,7 +46,7 @@ const derivativeTitle = i18n.translate('data.search.aggs.metrics.derivativeTitle
export const getDerivativeMetricAgg = ({
getInternalStartServices,
}: DerivativeMetricAggDependencies) => {
const { subtype, params, getFormat, getSerializedFormat } = parentPipelineAggHelper;
const { subtype, params, getSerializedFormat } = parentPipelineAggHelper;
return new MetricAggType(
{
@ -57,7 +57,6 @@ export const getDerivativeMetricAgg = ({
},
subtype,
params: [...params()],
getFormat,
getSerializedFormat,
},
{

View file

@ -18,14 +18,12 @@
*/
import { i18n } from '@kbn/i18n';
import { noop, identity } from 'lodash';
import { noop } from 'lodash';
import { forwardModifyAggConfigOnSearchRequestStart } from './nested_agg_helpers';
import { IMetricAggConfig, MetricAggParam } from '../metric_agg_type';
import { parentPipelineAggWriter } from './parent_pipeline_agg_writer';
import { FieldFormat } from '../../../../../common';
const metricAggFilter = [
'!top_hits',
'!percentiles',
@ -73,18 +71,6 @@ export const parentPipelineAggHelper = {
] as Array<MetricAggParam<IMetricAggConfig>>;
},
getFormat(agg: IMetricAggConfig) {
let subAgg;
const customMetric = agg.getParam('customMetric');
if (customMetric) {
subAgg = customMetric;
} else {
subAgg = agg.aggConfigs.byId(agg.getParam('metricAgg'));
}
return subAgg ? subAgg.type.getFormat(subAgg) : new (FieldFormat.from(identity))();
},
getSerializedFormat(agg: IMetricAggConfig) {
let subAgg;
const customMetric = agg.getParam('customMetric');

View file

@ -17,12 +17,10 @@
* under the License.
*/
import { identity } from 'lodash';
import { i18n } from '@kbn/i18n';
import { siblingPipelineAggWriter } from './sibling_pipeline_agg_writer';
import { forwardModifyAggConfigOnSearchRequestStart } from './nested_agg_helpers';
import { IMetricAggConfig, MetricAggParam } from '../metric_agg_type';
import { FieldFormat } from '../../../../../common';
const metricAggFilter: string[] = [
'!top_hits',
@ -87,13 +85,6 @@ export const siblingPipelineAggHelper = {
] as Array<MetricAggParam<IMetricAggConfig>>;
},
getFormat(agg: IMetricAggConfig) {
const customMetric = agg.getParam('customMetric');
return customMetric
? customMetric.type.getFormat(customMetric)
: new (FieldFormat.from(identity))();
},
getSerializedFormat(agg: IMetricAggConfig) {
const customMetric = agg.getParam('customMetric');
return customMetric ? customMetric.type.getSerializedFormat(customMetric) : {};

View file

@ -63,7 +63,6 @@ describe('AggTypeMetricMedianProvider class', () => {
],
{
typesRegistry,
fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats,
}
);
});

View file

@ -22,7 +22,6 @@ import { AggType, AggTypeConfig } from '../agg_type';
import { AggParamType } from '../param_types/agg';
import { AggConfig } from '../agg_config';
import { METRIC_TYPES } from './metric_agg_types';
import { KBN_FIELD_TYPES } from '../../../../common';
import { FieldTypes } from '../param_types';
import { GetInternalStartServicesFn } from '../../../types';
@ -82,14 +81,6 @@ export class MetricAggType<TMetricAggConfig extends AggConfig = IMetricAggConfig
return bucket[agg.id] && bucket[agg.id].value;
});
this.getFormat =
config.getFormat ||
((agg) => {
const { fieldFormats } = dependencies.getInternalStartServices();
const field = agg.getField();
return field ? field.format : fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER);
});
this.subtype =
config.subtype ||
i18n.translate('data.search.aggs.metrics.metricAggregationsSubtypeTitle', {

View file

@ -48,7 +48,7 @@ const movingAvgLabel = i18n.translate('data.search.aggs.metrics.movingAvgLabel',
export const getMovingAvgMetricAgg = ({
getInternalStartServices,
}: MovingAvgMetricAggDependencies) => {
const { subtype, params, getFormat, getSerializedFormat } = parentPipelineAggHelper;
const { subtype, params, getSerializedFormat } = parentPipelineAggHelper;
return new MetricAggType(
{
@ -57,7 +57,6 @@ export const getMovingAvgMetricAgg = ({
title: movingAvgTitle,
makeLabel: (agg) => makeNestedLabel(agg, movingAvgLabel),
subtype,
getFormat,
getSerializedFormat,
params: [
...params(),

View file

@ -24,14 +24,12 @@ import { getSerialDiffMetricAgg } from './serial_diff';
import { AggConfigs } from '../agg_configs';
import { mockAggTypesRegistry } from '../test_helpers';
import { IMetricAggConfig, MetricAggType } from './metric_agg_type';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { GetInternalStartServicesFn, InternalStartServices } from '../../../types';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
describe('parent pipeline aggs', function () {
const getInternalStartServices: GetInternalStartServicesFn = () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices);
@ -76,9 +74,7 @@ describe('parent pipeline aggs', function () {
const field = {
name: 'field',
format: {
type: {
id: 'bytes',
},
toJSON: () => ({ id: 'bytes' }),
},
};
const indexPattern = {
@ -111,7 +107,7 @@ describe('parent pipeline aggs', function () {
schema: 'metric',
},
],
{ typesRegistry, fieldFormats: getInternalStartServices().fieldFormats }
{ typesRegistry }
);
// Grab the aggConfig off the vis (we don't actually use the vis for anything else)
@ -197,14 +193,14 @@ describe('parent pipeline aggs', function () {
);
});
it('should have correct formatter', () => {
it('should have correct serialized format', () => {
init({
metricAgg: '3',
});
expect(metricAgg.getFormat(aggConfig).type.id).toBe('bytes');
expect(metricAgg.getSerializedFormat(aggConfig).id).toBe('bytes');
});
it('should have correct customMetric nested formatter', () => {
it('should have correct customMetric nested serialized format', () => {
init({
metricAgg: 'custom',
customMetric: {
@ -222,7 +218,7 @@ describe('parent pipeline aggs', function () {
schema: 'orderAgg',
},
});
expect(metricAgg.getFormat(aggConfig).type.id).toBe('bytes');
expect(metricAgg.getSerializedFormat(aggConfig).id).toBe('bytes');
});
it("should call modifyAggConfigOnSearchRequestStart for its customMetric's parameters", () => {

View file

@ -74,7 +74,7 @@ describe('AggTypesMetricsPercentileRanksProvider class', function () {
},
},
],
{ typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats }
{ typesRegistry }
);
});

View file

@ -22,7 +22,7 @@ import { MetricAggType } from './metric_agg_type';
import { getResponseAggConfigClass, IResponseAggConfig } from './lib/get_response_agg_config_class';
import { getPercentileValue } from './percentiles_get_value';
import { METRIC_TYPES } from './metric_agg_types';
import { FIELD_FORMAT_IDS, KBN_FIELD_TYPES } from '../../../../common';
import { KBN_FIELD_TYPES } from '../../../../common';
import { GetInternalStartServicesFn } from '../../../types';
import { BaseAggParams } from '../types';
@ -96,13 +96,6 @@ export const getPercentileRanksMetricAgg = ({
return values.map((value: any) => new ValueAggConfig(value));
},
getFormat() {
const { fieldFormats } = getInternalStartServices();
return (
fieldFormats.getInstance(FIELD_FORMAT_IDS.PERCENT) ||
fieldFormats.getDefaultInstance(KBN_FIELD_TYPES.NUMBER)
);
},
getSerializedFormat(agg) {
return {
id: 'percent',

View file

@ -67,7 +67,7 @@ describe('AggTypesMetricsPercentilesProvider class', () => {
},
},
],
{ typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats }
{ typesRegistry }
);
});

View file

@ -46,7 +46,7 @@ const serialDiffLabel = i18n.translate('data.search.aggs.metrics.serialDiffLabel
export const getSerialDiffMetricAgg = ({
getInternalStartServices,
}: SerialDiffMetricAggDependencies) => {
const { subtype, params, getFormat, getSerializedFormat } = parentPipelineAggHelper;
const { subtype, params, getSerializedFormat } = parentPipelineAggHelper;
return new MetricAggType(
{
@ -55,7 +55,6 @@ export const getSerialDiffMetricAgg = ({
makeLabel: (agg) => makeNestedLabel(agg, serialDiffLabel),
subtype,
params: [...params()],
getFormat,
getSerializedFormat,
},
{

View file

@ -25,14 +25,12 @@ import { getBucketMaxMetricAgg } from './bucket_max';
import { AggConfigs } from '../agg_configs';
import { IMetricAggConfig, MetricAggType } from './metric_agg_type';
import { mockAggTypesRegistry } from '../test_helpers';
import { fieldFormatsServiceMock } from '../../../field_formats/mocks';
import { GetInternalStartServicesFn, InternalStartServices } from '../../../types';
import { notificationServiceMock } from '../../../../../../../src/core/public/mocks';
describe('sibling pipeline aggs', () => {
const getInternalStartServices: GetInternalStartServicesFn = () =>
(({
fieldFormats: fieldFormatsServiceMock.createStartContract(),
notifications: notificationServiceMock.createStartContract(),
} as unknown) as InternalStartServices);
@ -71,9 +69,7 @@ describe('sibling pipeline aggs', () => {
const field = {
name: 'field',
format: {
type: {
id: 'bytes',
},
toJSON: () => ({ id: 'bytes' }),
},
};
const indexPattern = {
@ -112,7 +108,7 @@ describe('sibling pipeline aggs', () => {
},
},
],
{ typesRegistry, fieldFormats: getInternalStartServices().fieldFormats }
{ typesRegistry }
);
// Grab the aggConfig off the vis (we don't actually use the vis for anything else)
@ -155,7 +151,7 @@ describe('sibling pipeline aggs', () => {
expect(aggDsl.parentAggs['2-bucket'].aggs['2-metric'].avg.field).toEqual('field');
});
it('should have correct formatter', () => {
it('should have correct serialized field format', () => {
init({
customMetric: {
id: '5',
@ -171,7 +167,7 @@ describe('sibling pipeline aggs', () => {
},
});
expect(metricAgg.getFormat(aggConfig).type.id).toBe('bytes');
expect(metricAgg.getSerializedFormat(aggConfig).id).toBe('bytes');
});
it("should call modifyAggConfigOnSearchRequestStart for nested aggs' parameters", () => {

View file

@ -66,7 +66,7 @@ describe('AggTypeMetricStandardDeviationProvider class', () => {
},
},
],
{ typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats }
{ typesRegistry }
);
};

View file

@ -91,7 +91,7 @@ describe('Top hit metric', () => {
params,
},
],
{ typesRegistry, fieldFormats: aggTypesDependencies.getInternalStartServices().fieldFormats }
{ typesRegistry }
);
// Grab the aggConfig off the vis (we don't actually use the vis for anything else)

View file

@ -27,7 +27,6 @@ import {
} from './';
import { SearchAggsSetup, SearchAggsStart } from './types';
import { mockAggTypesRegistry } from './test_helpers';
import { fieldFormatsServiceMock } from '../../field_formats/mocks';
const aggTypeBaseParamMock = () => ({
name: 'some_param',
@ -73,7 +72,6 @@ export const searchAggsStartMock = (): SearchAggsStart => ({
createAggConfigs: jest.fn().mockImplementation((indexPattern, configStates = [], schemas) => {
return new AggConfigs(indexPattern, configStates, {
typesRegistry: mockAggTypesRegistry(),
fieldFormats: fieldFormatsServiceMock.createStartContract(),
});
}),
types: mockAggTypesRegistry(),

View file

@ -19,6 +19,7 @@
import { set } from 'lodash';
import { FormattedData } from '../../../../../plugins/inspector/public';
import { FormatFactory } from '../../../common/field_formats/utils';
import { TabbedTable } from '../tabify';
import { createFilter } from './create_filter';
@ -38,14 +39,30 @@ import { createFilter } from './create_filter';
*/
export async function buildTabularInspectorData(
table: TabbedTable,
queryFilter: { addFilters: (filter: any) => void }
{
queryFilter,
deserializeFieldFormat,
}: {
queryFilter: { addFilters: (filter: any) => void };
deserializeFieldFormat: FormatFactory;
}
) {
const aggConfigs = table.columns.map((column) => column.aggConfig);
const rows = table.rows.map((row) => {
return table.columns.reduce<Record<string, FormattedData>>((prev, cur, colIndex) => {
const value = row[cur.id];
const fieldFormatter = cur.aggConfig.fieldFormatter('text');
prev[`col-${colIndex}-${cur.aggConfig.id}`] = new FormattedData(value, fieldFormatter(value));
let format = cur.aggConfig.toSerializedFieldFormat();
if (Object.keys(format).length < 1) {
// If no format exists, fall back to string as a default
format = { id: 'string' };
}
const fieldFormatter = deserializeFieldFormat(format);
prev[`col-${colIndex}-${cur.aggConfig.id}`] = new FormattedData(
value,
fieldFormatter.convert(value)
);
return prev;
}, {});
});

View file

@ -22,12 +22,10 @@ import { AggConfigs, IAggConfig } from '../aggs';
import { TabbedTable } from '../tabify';
import { isRangeFilter, BytesFormat, FieldFormatsGetConfigFn } from '../../../common';
import { mockDataServices, mockAggTypesRegistry } from '../aggs/test_helpers';
import { fieldFormatsServiceMock } from '../../field_formats/mocks';
describe('createFilter', () => {
let table: TabbedTable;
let aggConfig: IAggConfig;
const fieldFormats = fieldFormatsServiceMock.createStartContract();
const typesRegistry = mockAggTypesRegistry();
@ -60,7 +58,7 @@ describe('createFilter', () => {
params,
},
],
{ typesRegistry, fieldFormats }
{ typesRegistry }
);
};

View file

@ -34,7 +34,12 @@ import { ISearchSource } from '../search_source';
import { tabifyAggResponse } from '../tabify';
import { Filter, Query, TimeRange, IIndexPattern, isRangeFilter } from '../../../common';
import { FilterManager, calculateBounds, getTime } from '../../query';
import { getSearchService, getQueryService, getIndexPatterns } from '../../services';
import {
getFieldFormats,
getIndexPatterns,
getQueryService,
getSearchService,
} from '../../services';
import { buildTabularInspectorData } from './build_tabular_inspector_data';
import { getRequestInspectorStats, getResponseInspectorStats, serializeAggConfig } from './utils';
@ -220,7 +225,11 @@ const handleCourierRequest = async ({
}
inspectorAdapters.data.setTabularLoader(
() => buildTabularInspectorData((searchSource as any).tabifiedResponse, filterManager),
() =>
buildTabularInspectorData((searchSource as any).tabifiedResponse, {
queryFilter: filterManager,
deserializeFieldFormat: getFieldFormats().deserialize,
}),
{ returnsFormattedValues: true }
);

View file

@ -38,7 +38,6 @@ import {
AggConfigs,
getCalculateAutoTimeExpression,
} from './aggs';
import { FieldFormatsStart } from '../field_formats';
import { ISearchGeneric } from './i_search';
interface SearchServiceSetupDependencies {
@ -50,7 +49,6 @@ interface SearchServiceSetupDependencies {
interface SearchServiceStartDependencies {
indexPatterns: IndexPatternsContract;
fieldFormats: FieldFormatsStart;
}
/**
@ -158,7 +156,6 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
calculateAutoTimeExpression: getCalculateAutoTimeExpression(core.uiSettings),
createAggConfigs: (indexPattern, configStates = [], schemas) => {
return new AggConfigs(indexPattern, configStates, {
fieldFormats: dependencies.fieldFormats,
typesRegistry: aggTypesStart,
});
},

View file

@ -21,7 +21,6 @@ import { tabifyGetColumns } from './get_columns';
import { TabbedAggColumn } from './types';
import { AggConfigs } from '../aggs';
import { mockAggTypesRegistry, mockDataServices } from '../aggs/test_helpers';
import { fieldFormatsServiceMock } from '../../field_formats/mocks';
describe('get columns', () => {
beforeEach(() => {
@ -29,7 +28,6 @@ describe('get columns', () => {
});
const typesRegistry = mockAggTypesRegistry();
const fieldFormats = fieldFormatsServiceMock.createStartContract();
const createAggConfigs = (aggs: any[] = []) => {
const field = {
@ -45,10 +43,7 @@ describe('get columns', () => {
},
} as any;
return new AggConfigs(indexPattern, aggs, {
typesRegistry,
fieldFormats,
});
return new AggConfigs(indexPattern, aggs, { typesRegistry });
};
test('should inject the metric after each bucket if the vis is hierarchical', () => {

View file

@ -21,7 +21,6 @@ import { TabbedAggResponseWriter } from './response_writer';
import { AggConfigs, BUCKET_TYPES } from '../aggs';
import { mockDataServices, mockAggTypesRegistry } from '../aggs/test_helpers';
import { TabbedResponseWriterOptions } from './types';
import { fieldFormatsServiceMock } from '../../field_formats/mocks';
describe('TabbedAggResponseWriter class', () => {
beforeEach(() => {
@ -31,7 +30,6 @@ describe('TabbedAggResponseWriter class', () => {
let responseWriter: TabbedAggResponseWriter;
const typesRegistry = mockAggTypesRegistry();
const fieldFormats = fieldFormatsServiceMock.createStartContract();
const splitAggConfig = [
{
@ -73,17 +71,11 @@ describe('TabbedAggResponseWriter class', () => {
},
} as any;
return new TabbedAggResponseWriter(
new AggConfigs(indexPattern, aggs, {
typesRegistry,
fieldFormats,
}),
{
metricsAtAllLevels: false,
partialRows: false,
...opts,
}
);
return new TabbedAggResponseWriter(new AggConfigs(indexPattern, aggs, { typesRegistry }), {
metricsAtAllLevels: false,
partialRows: false,
...opts,
});
};
describe('Constructor', () => {

View file

@ -22,11 +22,9 @@ import { IndexPattern } from '../../index_patterns';
import { AggConfigs, IAggConfig, IAggConfigs } from '../aggs';
import { mockAggTypesRegistry } from '../aggs/test_helpers';
import { metricOnly, threeTermBuckets } from 'fixtures/fake_hierarchical_data';
import { fieldFormatsServiceMock } from '../../field_formats/mocks';
describe('tabifyAggResponse Integration', () => {
const typesRegistry = mockAggTypesRegistry();
const fieldFormats = fieldFormatsServiceMock.createStartContract();
const createAggConfigs = (aggs: IAggConfig[] = []) => {
const field = {
@ -42,10 +40,7 @@ describe('tabifyAggResponse Integration', () => {
},
} as unknown) as IndexPattern;
return new AggConfigs(indexPattern, aggs, {
typesRegistry,
fieldFormats,
});
return new AggConfigs(indexPattern, aggs, { typesRegistry });
};
const mockAggConfig = (agg: any): IAggConfig => (agg as unknown) as IAggConfig;

View file

@ -46,7 +46,7 @@ function TableOptions({
}),
},
...tabifyGetColumns(aggs.getResponseAggs(), true)
.filter((col) => get(col.aggConfig.type.getFormat(col.aggConfig), 'type.id') === 'number')
.filter((col) => get(col.aggConfig.toSerializedFieldFormat(), 'id') === 'number')
.map(({ name }) => ({ value: name, text: name })),
],
[aggs]

View file

@ -207,7 +207,7 @@ export default function ({ getService, getPageObjects }) {
const vizName1 = 'Visualization TileMap';
await PageObjects.visualize.loadSavedVisualization(vizName1);
await inspector.open();
await inspector.expectTableHeaders(['filter', 'geohash_grid', 'Count', 'Geo Centroid']);
await inspector.expectTableHeaders(['Filter', 'Geohash', 'Count', 'Geo Centroid']);
await inspector.close();
});
@ -216,7 +216,7 @@ export default function ({ getService, getPageObjects }) {
await PageObjects.visEditor.setIsFilteredByCollarCheckbox(false);
await PageObjects.visEditor.clickGo();
await inspector.open();
await inspector.expectTableHeaders(['geohash_grid', 'Count', 'Geo Centroid']);
await inspector.expectTableHeaders(['Geohash', 'Count', 'Geo Centroid']);
await inspector.close();
});

View file

@ -712,7 +712,6 @@
"data.search.aggs.aggGroups.bucketsText": "バケット",
"data.search.aggs.aggGroups.metricsText": "メトリック",
"data.search.aggs.aggGroups.noneText": "なし",
"data.search.aggs.aggTypes.rangesFormatMessage": "{gte} {from} と {lt} {to}",
"data.search.aggs.aggTypesLabel": "{fieldName} の範囲",
"data.search.aggs.buckets.dateHistogram.customLabel.help": "このアグリゲーションのカスタムラベルを表します",
"data.search.aggs.buckets.dateHistogram.dropPartials.help": "このアグリゲーションでdrop_partialsを使用するかどうかを指定します",

View file

@ -713,7 +713,6 @@
"data.search.aggs.aggGroups.bucketsText": "存储桶",
"data.search.aggs.aggGroups.metricsText": "指标",
"data.search.aggs.aggGroups.noneText": "无",
"data.search.aggs.aggTypes.rangesFormatMessage": "{gte} {from} 和 {lt} {to}",
"data.search.aggs.aggTypesLabel": "{fieldName} 范围",
"data.search.aggs.buckets.dateHistogram.customLabel.help": "表示此聚合的定制标签",
"data.search.aggs.buckets.dateHistogram.dropPartials.help": "指定是否将 drop_partials 用于此聚合",