Add Significant Text agg to AggConfigs (#122166)

This commit is contained in:
Anton Dosov 2022-01-05 16:56:50 +01:00 committed by GitHub
parent 72297e5cdd
commit 673c88f7b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 551 additions and 6 deletions

View file

@ -59,6 +59,7 @@ export const getAggTypes = () => ({
{ name: BUCKET_TYPES.FILTER, fn: buckets.getFilterBucketAgg },
{ name: BUCKET_TYPES.FILTERS, fn: buckets.getFiltersBucketAgg },
{ name: BUCKET_TYPES.SIGNIFICANT_TERMS, fn: buckets.getSignificantTermsBucketAgg },
{ name: BUCKET_TYPES.SIGNIFICANT_TEXT, fn: buckets.getSignificantTextBucketAgg },
{ name: BUCKET_TYPES.GEOHASH_GRID, fn: buckets.getGeoHashBucketAgg },
{ name: BUCKET_TYPES.GEOTILE_GRID, fn: buckets.getGeoTitleBucketAgg },
{ name: BUCKET_TYPES.SAMPLER, fn: buckets.getSamplerBucketAgg },
@ -71,6 +72,7 @@ export const getAggTypesFunctions = () => [
buckets.aggFilter,
buckets.aggFilters,
buckets.aggSignificantTerms,
buckets.aggSignificantText,
buckets.aggIpRange,
buckets.aggDateRange,
buckets.aggRange,

View file

@ -71,6 +71,7 @@ describe('Aggs service', () => {
"filter",
"filters",
"significant_terms",
"significant_text",
"geohash_grid",
"geotile_grid",
"sampler",
@ -122,6 +123,7 @@ describe('Aggs service', () => {
"filter",
"filters",
"significant_terms",
"significant_text",
"geohash_grid",
"geotile_grid",
"sampler",

View file

@ -8,9 +8,10 @@
import moment from 'moment';
import { IAggConfig } from '../agg_config';
import { GenericBucket, IAggConfigs, KBN_FIELD_TYPES } from '../../../../common';
import { FilterFieldFn, GenericBucket, IAggConfigs } from '../../../../common';
import { AggType, AggTypeConfig } from '../agg_type';
import { AggParamType } from '../param_types/agg';
import type { FieldTypes } from '../param_types/field';
export interface IBucketAggConfig extends IAggConfig {
type: InstanceType<typeof BucketAggType>;
@ -19,7 +20,14 @@ export interface IBucketAggConfig extends IAggConfig {
export interface BucketAggParam<TBucketAggConfig extends IAggConfig>
extends AggParamType<TBucketAggConfig> {
scriptable?: boolean;
filterFieldTypes?: KBN_FIELD_TYPES | KBN_FIELD_TYPES[] | '*';
filterFieldTypes?: FieldTypes;
onlyAggregatable?: boolean;
/**
* Filter available fields by passing filter fn on a {@link DataViewField}
* If used, takes precedence over filterFieldTypes and other filter params
*/
filterField?: FilterFieldFn;
}
const bucketType = 'buckets';

View file

@ -16,6 +16,7 @@ export enum BUCKET_TYPES {
TERMS = 'terms',
MULTI_TERMS = 'multi_terms',
SIGNIFICANT_TERMS = 'significant_terms',
SIGNIFICANT_TEXT = 'significant_text',
GEOHASH_GRID = 'geohash_grid',
GEOTILE_GRID = 'geotile_grid',
DATE_HISTOGRAM = 'date_histogram',

View file

@ -34,6 +34,8 @@ export * from './range_fn';
export * from './range';
export * from './significant_terms_fn';
export * from './significant_terms';
export * from './significant_text_fn';
export * from './significant_text';
export * from './terms_fn';
export * from './terms';
export * from './multi_terms_fn';

View file

@ -0,0 +1,89 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { AggConfigs } from '../agg_configs';
import { mockAggTypesRegistry } from '../test_helpers';
import { BUCKET_TYPES } from './bucket_agg_types';
describe('Significant Text Agg', () => {
const getAggConfigs = (params: Record<string, any> = {}) => {
const indexPattern = {
id: '1234',
title: 'logstash-*',
fields: {
getByName: () => field,
filter: () => [field],
},
} as any;
const field = {
name: 'field',
indexPattern,
};
return new AggConfigs(
indexPattern,
[
{
id: 'test',
type: BUCKET_TYPES.SIGNIFICANT_TEXT,
params,
},
],
{
typesRegistry: mockAggTypesRegistry(),
}
);
};
test('produces the expected expression ast', () => {
const aggConfigs = getAggConfigs({
size: 'SIZE',
field: {
name: 'FIELD',
},
});
expect(aggConfigs.aggs[0].toExpressionAst()).toMatchInlineSnapshot(`
Object {
"chain": Array [
Object {
"arguments": Object {
"enabled": Array [
true,
],
"field": Array [
"FIELD",
],
"id": Array [
"test",
],
"size": Array [
"SIZE",
],
},
"function": "aggSignificantText",
"type": "function",
},
],
"type": "expression",
}
`);
});
test('should generate correct label', () => {
const aggConfigs = getAggConfigs({
size: 'SIZE',
field: {
name: 'FIELD',
},
});
const label = aggConfigs.aggs[0].makeLabel();
expect(label).toBe('Top SIZE unusual terms from "FIELD" text');
});
});

View file

@ -0,0 +1,90 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { i18n } from '@kbn/i18n';
import { BucketAggType } from './bucket_agg_type';
import { migrateIncludeExcludeFormat } from './migrate_include_exclude_format';
import { BUCKET_TYPES } from './bucket_agg_types';
import { aggSignificantTextFnName } from './significant_text_fn';
import { KBN_FIELD_TYPES, ES_FIELD_TYPES } from '../../../../common';
import { BaseAggParams } from '../types';
import { createFilterTerms } from './create_filter/terms';
const significantTextTitle = i18n.translate('data.search.aggs.buckets.significantTextTitle', {
defaultMessage: 'Significant Text',
});
export interface AggParamsSignificantText extends BaseAggParams {
field: string;
size?: number;
min_doc_count?: number;
filter_duplicate_text?: boolean;
exclude?: string;
include?: string;
}
export const getSignificantTextBucketAgg = () =>
new BucketAggType({
name: BUCKET_TYPES.SIGNIFICANT_TEXT,
expressionName: aggSignificantTextFnName,
title: significantTextTitle,
makeLabel(aggConfig) {
return i18n.translate('data.search.aggs.buckets.significantTextLabel', {
defaultMessage: 'Top {size} unusual terms from "{fieldName}" text',
values: {
size: aggConfig.params.size,
fieldName: aggConfig.getFieldDisplayName(),
},
});
},
createFilter: createFilterTerms,
params: [
{
name: 'field',
type: 'field',
/**
* Significant text is available only for ES_FIELD_TYPES.TEXT,
* This information is not available from field.type, so we have to check this using underlying esTypes
*/
filterField: (field) =>
Boolean(
field.type === KBN_FIELD_TYPES.STRING && field.esTypes?.includes(ES_FIELD_TYPES.TEXT)
),
},
{
name: 'size',
type: 'number',
},
{
name: 'min_doc_count',
type: 'number',
},
{
name: 'filter_duplicate_text',
type: 'boolean',
},
{
name: 'exclude',
displayName: i18n.translate('data.search.aggs.buckets.significantText.excludeLabel', {
defaultMessage: 'Exclude',
}),
type: 'string',
advanced: true,
...migrateIncludeExcludeFormat,
},
{
name: 'include',
displayName: i18n.translate('data.search.aggs.buckets.significantText.includeLabel', {
defaultMessage: 'Include',
}),
type: 'string',
advanced: true,
...migrateIncludeExcludeFormat,
},
],
});

View file

@ -0,0 +1,85 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { functionWrapper } from '../test_helpers';
import { aggSignificantText } from './significant_text_fn';
describe('agg_expression_functions', () => {
describe('aggSignificantText', () => {
const fn = functionWrapper(aggSignificantText());
test('fills in defaults when only required args are provided', () => {
const actual = fn({
field: 'machine.os',
});
expect(actual).toMatchInlineSnapshot(`
Object {
"type": "agg_type",
"value": Object {
"enabled": true,
"id": undefined,
"params": Object {
"customLabel": undefined,
"exclude": undefined,
"field": "machine.os",
"filter_duplicate_text": undefined,
"include": undefined,
"json": undefined,
"min_doc_count": undefined,
"size": undefined,
},
"schema": undefined,
"type": "significant_text",
},
}
`);
});
test('includes optional params when they are provided', () => {
const actual = fn({
id: '1',
enabled: false,
schema: 'whatever',
field: 'machine.os',
size: 6,
include: 'win',
exclude: 'ios',
filter_duplicate_text: true,
min_doc_count: 10,
});
expect(actual.value).toMatchInlineSnapshot(`
Object {
"enabled": false,
"id": "1",
"params": Object {
"customLabel": undefined,
"exclude": "ios",
"field": "machine.os",
"filter_duplicate_text": true,
"include": "win",
"json": undefined,
"min_doc_count": 10,
"size": 6,
},
"schema": "whatever",
"type": "significant_text",
}
`);
});
test('correctly parses json string argument', () => {
const actual = fn({
field: 'machine.os',
json: '{ "foo": true }',
});
expect(actual.value.params.json).toEqual('{ "foo": true }');
});
});
});

View file

@ -0,0 +1,120 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { i18n } from '@kbn/i18n';
import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { AggExpressionType, AggExpressionFunctionArgs, BUCKET_TYPES } from '../';
export const aggSignificantTextFnName = 'aggSignificantText';
type Input = any;
type AggArgs = AggExpressionFunctionArgs<typeof BUCKET_TYPES.SIGNIFICANT_TEXT>;
type Arguments = AggArgs;
type Output = AggExpressionType;
type FunctionDefinition = ExpressionFunctionDefinition<
typeof aggSignificantTextFnName,
Input,
Arguments,
Output
>;
export const aggSignificantText = (): FunctionDefinition => ({
name: aggSignificantTextFnName,
help: i18n.translate('data.search.aggs.function.buckets.significantText.help', {
defaultMessage: 'Generates a serialized agg config for a Significant Text agg',
}),
type: 'agg_type',
args: {
id: {
types: ['string'],
help: i18n.translate('data.search.aggs.buckets.significantText.id.help', {
defaultMessage: 'ID for this aggregation',
}),
},
enabled: {
types: ['boolean'],
default: true,
help: i18n.translate('data.search.aggs.buckets.significantText.enabled.help', {
defaultMessage: 'Specifies whether this aggregation should be enabled',
}),
},
schema: {
types: ['string'],
help: i18n.translate('data.search.aggs.buckets.significantText.schema.help', {
defaultMessage: 'Schema to use for this aggregation',
}),
},
field: {
types: ['string'],
required: true,
help: i18n.translate('data.search.aggs.buckets.significantText.field.help', {
defaultMessage: 'Field to use for this aggregation',
}),
},
size: {
types: ['number'],
help: i18n.translate('data.search.aggs.buckets.significantText.size.help', {
defaultMessage: 'Max number of buckets to retrieve',
}),
},
min_doc_count: {
types: ['number'],
help: i18n.translate('data.search.aggs.buckets.significantText.minDocCount.help', {
defaultMessage: 'Return terms that match more than a configured number',
}),
},
filter_duplicate_text: {
types: ['boolean'],
help: i18n.translate('data.search.aggs.buckets.significantText.filterDuplicateText.help', {
defaultMessage: 'Filtering near-duplicate text',
}),
},
exclude: {
types: ['string'],
help: i18n.translate('data.search.aggs.buckets.significantText.exclude.help', {
defaultMessage: 'Specific bucket values to exclude from results',
}),
},
include: {
types: ['string'],
help: i18n.translate('data.search.aggs.buckets.significantText.include.help', {
defaultMessage: 'Specific bucket values to include in results',
}),
},
json: {
types: ['string'],
help: i18n.translate('data.search.aggs.buckets.significantText.json.help', {
defaultMessage: 'Advanced json to include when the agg is sent to Elasticsearch',
}),
},
customLabel: {
types: ['string'],
help: i18n.translate('data.search.aggs.buckets.significantText.customLabel.help', {
defaultMessage: 'Represents a custom label for this aggregation',
}),
},
},
fn: (input, args) => {
const { id, enabled, schema, ...rest } = args;
return {
type: 'agg_type',
value: {
id,
enabled,
schema,
type: BUCKET_TYPES.SIGNIFICANT_TEXT,
params: {
...rest,
},
},
};
},
});

View file

@ -91,5 +91,47 @@ describe('Field', () => {
expect(fields.length).toBe(2);
});
it('should filter by KBN type', () => {
const aggParam = new FieldParamType({
name: 'field',
type: 'field',
filterFieldTypes: KBN_FIELD_TYPES.NUMBER,
});
const fields = aggParam.getAvailableFields(agg);
expect(fields.length).toBe(1);
expect(fields[0]).toBe(indexPattern.fields[0]);
});
it('should filter by field filter predicate', () => {
const aggParam = new FieldParamType({
name: 'field',
type: 'field',
filterField: (field: typeof indexPattern['fields'][0]) =>
field.esTypes?.includes(ES_FIELD_TYPES.TEXT),
});
const fields = aggParam.getAvailableFields(agg);
expect(fields.length).toBe(1);
expect(fields[0]).toBe(indexPattern.fields[1]);
});
it('should filter by field filter predicate and ignore other filter settings', () => {
const aggParam = new FieldParamType({
name: 'field',
type: 'field',
filterField: (field: typeof indexPattern['fields'][0]) =>
field.esTypes?.includes(ES_FIELD_TYPES.TEXT),
filterFieldTypes: KBN_FIELD_TYPES.NUMBER,
});
const fields = aggParam.getAvailableFields(agg);
expect(fields.length).toBe(1);
expect(fields[0]).toBe(indexPattern.fields[1]);
});
});
});

View file

@ -15,11 +15,14 @@ import {
import { BaseParamType } from './base';
import { propFilter } from '../utils';
import { KBN_FIELD_TYPES } from '../../../kbn_field_types/types';
import { isNestedField, IndexPatternField } from '../../../../../data_views/common';
import { isNestedField, IndexPatternField, DataViewField } from '../../../../../data_views/common';
const filterByType = propFilter('type');
export type FieldTypes = KBN_FIELD_TYPES | KBN_FIELD_TYPES[] | '*';
export type FilterFieldFn = (field: DataViewField) => boolean;
// TODO need to make a more explicit interface for this
export type IFieldParamType = FieldParamType;
@ -29,11 +32,18 @@ export class FieldParamType extends BaseParamType {
filterFieldTypes: FieldTypes;
onlyAggregatable: boolean;
/**
* Filter available fields by passing filter fn on a {@link DataViewField}
* If used, takes precedence over filterFieldTypes and other filter params
*/
filterField?: FilterFieldFn;
constructor(config: Record<string, any>) {
super(config);
this.filterFieldTypes = config.filterFieldTypes || '*';
this.onlyAggregatable = config.onlyAggregatable !== false;
this.filterField = config.filterField;
if (!config.write) {
this.write = (aggConfig: IAggConfig, output: Record<string, any>) => {
@ -126,7 +136,11 @@ export class FieldParamType extends BaseParamType {
getAvailableFields = (aggConfig: IAggConfig) => {
const fields = aggConfig.getIndexPattern().fields;
const filteredFields = fields.filter((field: IndexPatternField) => {
const { onlyAggregatable, scriptable, filterFieldTypes } = this;
const { onlyAggregatable, scriptable, filterFieldTypes, filterField } = this;
if (filterField) {
return filterField(field);
}
if (
(onlyAggregatable && (!field.aggregatable || isNestedField(field))) ||

View file

@ -92,6 +92,7 @@ import {
} from './';
import { AggParamsSampler } from './buckets/sampler';
import { AggParamsDiversifiedSampler } from './buckets/diversified_sampler';
import { AggParamsSignificantText } from './buckets/significant_text';
export type { IAggConfig, AggConfigSerialized } from './agg_config';
export type { CreateAggConfigParams, IAggConfigs } from './agg_configs';
@ -158,6 +159,7 @@ export interface AggParamsMapping {
[BUCKET_TYPES.FILTER]: AggParamsFilter;
[BUCKET_TYPES.FILTERS]: AggParamsFilters;
[BUCKET_TYPES.SIGNIFICANT_TERMS]: AggParamsSignificantTerms;
[BUCKET_TYPES.SIGNIFICANT_TEXT]: AggParamsSignificantText;
[BUCKET_TYPES.GEOTILE_GRID]: AggParamsGeoTile;
[BUCKET_TYPES.GEOHASH_GRID]: AggParamsGeoHash;
[BUCKET_TYPES.HISTOGRAM]: AggParamsHistogram;

View file

@ -53,7 +53,7 @@ describe('AggsService - public', () => {
test('registers default agg types', () => {
service.setup(setupDeps);
const start = service.start(startDeps);
expect(start.types.getAll().buckets.length).toBe(14);
expect(start.types.getAll().buckets.length).toBe(15);
expect(start.types.getAll().metrics.length).toBe(23);
});
@ -69,7 +69,7 @@ describe('AggsService - public', () => {
);
const start = service.start(startDeps);
expect(start.types.getAll().buckets.length).toBe(15);
expect(start.types.getAll().buckets.length).toBe(16);
expect(start.types.getAll().buckets.some(({ name }) => name === 'foo')).toBe(true);
expect(start.types.getAll().metrics.length).toBe(24);
expect(start.types.getAll().metrics.some(({ name }) => name === 'bar')).toBe(true);

View file

@ -105,6 +105,7 @@ export const getHeatmapVisTypeDefinition = ({
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
{
@ -120,6 +121,7 @@ export const getHeatmapVisTypeDefinition = ({
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
{
@ -142,6 +144,7 @@ export const getHeatmapVisTypeDefinition = ({
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
],

View file

@ -93,6 +93,7 @@ export const createMetricVisTypeDefinition = (): VisTypeDefinition<VisParams> =>
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
],

View file

@ -94,6 +94,7 @@ export const samplePieVis = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
editor: false,
params: [],
@ -112,6 +113,7 @@ export const samplePieVis = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
params: [
{

View file

@ -94,6 +94,7 @@ export const getPieVisTypeDefinition = ({
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
{
@ -112,6 +113,7 @@ export const getPieVisTypeDefinition = ({
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
],

View file

@ -139,6 +139,7 @@ export const gaugeVisTypeDefinition: VisTypeDefinition<GaugeVisParams> = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
],

View file

@ -103,6 +103,7 @@ export const goalVisTypeDefinition: VisTypeDefinition<GaugeVisParams> = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
],

View file

@ -632,6 +632,7 @@ export const getVis = (bucketType: string) => {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
params: [],
},
@ -648,6 +649,7 @@ export const getVis = (bucketType: string) => {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
params: [],
},
@ -664,6 +666,7 @@ export const getVis = (bucketType: string) => {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
params: [
{
@ -716,6 +719,7 @@ export const getVis = (bucketType: string) => {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
params: [],
},
@ -732,6 +736,7 @@ export const getVis = (bucketType: string) => {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
params: [],
},
@ -748,6 +753,7 @@ export const getVis = (bucketType: string) => {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
params: [
{
@ -771,6 +777,7 @@ export const getVis = (bucketType: string) => {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
params: [],
},
@ -787,6 +794,7 @@ export const getVis = (bucketType: string) => {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
params: [],
},
@ -803,6 +811,7 @@ export const getVis = (bucketType: string) => {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
params: [
{

View file

@ -156,6 +156,7 @@ export const sampleAreaVis = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
editor: false,
params: [],
@ -173,6 +174,7 @@ export const sampleAreaVis = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
editor: false,
params: [],
@ -190,6 +192,7 @@ export const sampleAreaVis = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
params: [
{

View file

@ -164,6 +164,7 @@ export const areaVisTypeDefinition = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
{
@ -181,6 +182,7 @@ export const areaVisTypeDefinition = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
{
@ -198,6 +200,7 @@ export const areaVisTypeDefinition = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
],

View file

@ -167,6 +167,7 @@ export const histogramVisTypeDefinition = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
{
@ -184,6 +185,7 @@ export const histogramVisTypeDefinition = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
{
@ -201,6 +203,7 @@ export const histogramVisTypeDefinition = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
],

View file

@ -166,6 +166,7 @@ export const horizontalBarVisTypeDefinition = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
{
@ -183,6 +184,7 @@ export const horizontalBarVisTypeDefinition = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
{
@ -200,6 +202,7 @@ export const horizontalBarVisTypeDefinition = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
],

View file

@ -158,6 +158,7 @@ export const lineVisTypeDefinition = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
{
@ -175,6 +176,7 @@ export const lineVisTypeDefinition = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
{
@ -192,6 +194,7 @@ export const lineVisTypeDefinition = {
'!sampler',
'!diversified_sampler',
'!multi_terms',
'!significant_text',
],
},
],

View file

@ -0,0 +1,53 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import expect from '@kbn/expect';
import { ExpectExpression, expectExpressionProvider } from './helpers';
import { FtrProviderContext } from '../../../functional/ftr_provider_context';
export default function ({
getService,
updateBaselines,
}: FtrProviderContext & { updateBaselines: boolean }) {
let expectExpression: ExpectExpression;
describe('esaggs_significanttext', () => {
before(() => {
expectExpression = expectExpressionProvider({ getService, updateBaselines });
});
const timeRange = {
from: '2015-09-21T00:00:00Z',
to: '2015-09-22T00:00:00Z',
};
describe('aggSignificantText', () => {
it('can execute aggSignificantText', async () => {
const expression = `
kibana_context timeRange={timerange from='${timeRange.from}' to='${timeRange.to}'}
| esaggs index={indexPatternLoad id='logstash-*'}
aggs={aggSignificantText id="1" enabled=true schema="bucket" field="headings" size=10}
aggs={aggCount id="2" enabled=true schema="metric"}
`;
const result = await expectExpression('sampler', expression).getResponse();
expect(result.columns.length).to.be(2);
const significantTermColumn = result.columns[0];
expect(significantTermColumn.name).to.be('Top 10 unusual terms from "headings" text');
const countColumn = result.columns[1];
expect(countColumn.name).to.be('Count');
expect(result.rows.length).to.be(10);
expect(result.rows[0]['col-0-1']).to.be('facebook.com');
expect(result.rows[0]['col-1-2']).to.be(815);
});
});
});
}

View file

@ -45,5 +45,6 @@ export default function ({ getService, getPageObjects, loadTestFile }: FtrProvid
loadTestFile(require.resolve('./esaggs_timeshift'));
loadTestFile(require.resolve('./esaggs_multiterms'));
loadTestFile(require.resolve('./esaggs_sampler'));
loadTestFile(require.resolve('./esaggs_significanttext'));
});
}