diff --git a/src/plugins/data/common/search/aggs/agg_configs.test.ts b/src/plugins/data/common/search/aggs/agg_configs.test.ts index 8ea53ddd3270c..83e0d5b78d080 100644 --- a/src/plugins/data/common/search/aggs/agg_configs.test.ts +++ b/src/plugins/data/common/search/aggs/agg_configs.test.ts @@ -7,6 +7,7 @@ */ import { keyBy } from 'lodash'; +import { ExpressionAstExpression, buildExpression } from '@kbn/expressions-plugin/common'; import { AggConfig } from './agg_config'; import { AggConfigs } from './agg_configs'; import { AggTypesRegistryStart } from './agg_types_registry'; @@ -787,4 +788,62 @@ describe('AggConfigs', () => { }); }); }); + + describe('#toExpressionAst', () => { + function toString(ast: ExpressionAstExpression) { + return buildExpression(ast).toString(); + } + + it('should generate the `index` argument', () => { + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + + expect(toString(ac.toExpressionAst())).toMatchInlineSnapshot( + `"esaggs index={indexPatternLoad id=\\"logstash-*\\"}"` + ); + }); + + it('should generate the `metricsAtAllLevels` if hierarchical', () => { + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + ac.hierarchical = true; + + expect(toString(ac.toExpressionAst())).toMatchInlineSnapshot( + `"esaggs index={indexPatternLoad id=\\"logstash-*\\"} metricsAtAllLevels=true"` + ); + }); + + it('should generate the `partialRows` argument', () => { + const ac = new AggConfigs(indexPattern, [], { typesRegistry }); + ac.partialRows = true; + + expect(toString(ac.toExpressionAst())).toMatchInlineSnapshot( + `"esaggs index={indexPatternLoad id=\\"logstash-*\\"} partialRows=true"` + ); + }); + + it('should generate the `aggs` argument', () => { + const configStates = [ + { + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: { field: '@timestamp', interval: '10s' }, + }, + { enabled: true, type: 'avg', schema: 'metric', params: { field: 'bytes' } }, + { enabled: true, type: 'sum', schema: 'metric', params: { field: 'bytes' } }, + { enabled: true, type: 'min', schema: 'metric', params: { field: 'bytes' } }, + { enabled: true, type: 'max', schema: 'metric', params: { field: 'bytes' } }, + ]; + + const ac = new AggConfigs(indexPattern, configStates, { typesRegistry }); + + expect(toString(ac.toExpressionAst())).toMatchInlineSnapshot(` + "esaggs index={indexPatternLoad id=\\"logstash-*\\"} + aggs={aggDateHistogram field=\\"@timestamp\\" useNormalizedEsInterval=true extendToTimeRange=false scaleMetricValues=false interval=\\"10s\\" drop_partials=false min_doc_count=1 extended_bounds={extendedBounds} id=\\"1\\" enabled=true schema=\\"segment\\"} + aggs={aggAvg field=\\"bytes\\" id=\\"2\\" enabled=true schema=\\"metric\\"} + aggs={aggSum field=\\"bytes\\" emptyAsNull=false id=\\"3\\" enabled=true schema=\\"metric\\"} + aggs={aggMin field=\\"bytes\\" id=\\"4\\" enabled=true schema=\\"metric\\"} + aggs={aggMax field=\\"bytes\\" id=\\"5\\" enabled=true schema=\\"metric\\"}" + `); + }); + }); }); diff --git a/src/plugins/data/common/search/aggs/agg_configs.ts b/src/plugins/data/common/search/aggs/agg_configs.ts index fcb51b63df668..e7fba622dd598 100644 --- a/src/plugins/data/common/search/aggs/agg_configs.ts +++ b/src/plugins/data/common/search/aggs/agg_configs.ts @@ -13,6 +13,8 @@ import { Assign } from '@kbn/utility-types'; import { isRangeFilter } from '@kbn/es-query'; import type { DataView } from '@kbn/data-views-plugin/common'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { IndexPatternLoadExpressionFunctionDefinition } from '@kbn/data-views-plugin/common'; +import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/common'; import { IEsSearchResponse, @@ -21,6 +23,7 @@ import { RangeFilter, // eslint-disable-next-line @kbn/eslint/no-restricted-paths } from '../../../public'; +import type { EsaggsExpressionFunctionDefinition } from '../expressions'; import { AggConfig, AggConfigSerialized, IAggConfig } from './agg_config'; import { IAggType } from './agg_type'; import { AggTypesRegistryStart } from './agg_types_registry'; @@ -55,6 +58,7 @@ function parseParentAggs(dslLvlCursor: any, dsl: any) { export interface AggConfigsOptions { typesRegistry: AggTypesRegistryStart; hierarchical?: boolean; + partialRows?: boolean; } export type CreateAggConfigParams = Assign; @@ -83,6 +87,7 @@ export class AggConfigs { public timeFields?: string[]; public forceNow?: Date; public hierarchical?: boolean = false; + public partialRows?: boolean = false; private readonly typesRegistry: AggTypesRegistryStart; @@ -100,6 +105,7 @@ export class AggConfigs { this.aggs = []; this.indexPattern = indexPattern; this.hierarchical = opts.hierarchical; + this.partialRows = opts.partialRows; configStates.forEach((params: any) => this.createAggConfig(params)); } @@ -493,4 +499,26 @@ export class AggConfigs { this.getRequestAggs().map((agg: AggConfig) => agg.onSearchRequestStart(searchSource, options)) ); } + + /** + * Generates an expression abstract syntax tree using the `esaggs` expression function. + * @returns The expression AST. + */ + toExpressionAst() { + return buildExpression([ + buildExpressionFunction('esaggs', { + index: buildExpression([ + buildExpressionFunction( + 'indexPatternLoad', + { + id: this.indexPattern.id!, + } + ), + ]), + metricsAtAllLevels: this.hierarchical, + partialRows: this.partialRows, + aggs: this.aggs.map((agg) => buildExpression(agg.toExpressionAst())), + }), + ]).toAst(); + } } diff --git a/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts b/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts index 33b4d0cb5d51e..e316652da8cbe 100644 --- a/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts +++ b/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts @@ -40,6 +40,7 @@ describe('esaggs expression function - public', () => { abortSignal: jest.fn() as unknown as jest.Mocked, aggs: { aggs: [{ type: { name: 'terms', postFlightRequest: jest.fn().mockResolvedValue({}) } }], + partialRows: false, setTimeRange: jest.fn(), toDsl: jest.fn().mockReturnValue({ aggs: {} }), onSearchRequestStart: jest.fn(), @@ -49,7 +50,6 @@ describe('esaggs expression function - public', () => { filters: undefined, indexPattern: { id: 'logstash-*' } as unknown as jest.Mocked, inspectorAdapters: {}, - partialRows: false, query: undefined, searchSessionId: 'abc123', searchSourceService: searchSourceCommonMock, @@ -147,7 +147,7 @@ describe('esaggs expression function - public', () => { mockParams.aggs, {}, { - partialRows: mockParams.partialRows, + partialRows: mockParams.aggs.partialRows, timeRange: mockParams.timeRange, } ); diff --git a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts index 7d8aadf2cad3b..8caa93c4461ef 100644 --- a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts +++ b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts @@ -24,8 +24,6 @@ interface RequestHandlerParams { filters?: Filter[]; indexPattern?: DataView; inspectorAdapters: Adapters; - metricsAtAllLevels?: boolean; - partialRows?: boolean; query?: Query; searchSessionId?: string; searchSourceService: ISearchStartSearchSource; @@ -41,7 +39,6 @@ export const handleRequest = ({ filters, indexPattern, inspectorAdapters, - partialRows, query, searchSessionId, searchSourceService, @@ -131,7 +128,7 @@ export const handleRequest = ({ const parsedTimeRange = timeRange ? calculateBounds(timeRange, { forceNow }) : null; const tabifyParams = { metricsAtAllLevels: aggs.hierarchical, - partialRows, + partialRows: aggs.partialRows, timeRange: parsedTimeRange ? { from: parsedTimeRange.min, to: parsedTimeRange.max, timeFields: allTimeFields } : undefined, diff --git a/src/plugins/data/common/search/expressions/kibana_context.test.ts b/src/plugins/data/common/search/expressions/kibana_context.test.ts index 3e07366b76c2d..b69809bd9d981 100644 --- a/src/plugins/data/common/search/expressions/kibana_context.test.ts +++ b/src/plugins/data/common/search/expressions/kibana_context.test.ts @@ -89,16 +89,28 @@ describe('kibanaContextFn', () => { } as any); const args = { ...emptyArgs, - q: { - type: 'kibana_query' as 'kibana_query', - language: 'test', - query: { - type: 'test', - match_phrase: { - test: 'something2', + q: [ + { + type: 'kibana_query' as 'kibana_query', + language: 'test', + query: { + type: 'test', + match_phrase: { + test: 'something2', + }, }, }, - }, + { + type: 'kibana_query' as 'kibana_query', + language: 'test', + query: { + type: 'test', + match_phrase: { + test: 'something3', + }, + }, + }, + ], savedSearchId: 'test', }; const input: KibanaContext = { @@ -183,6 +195,16 @@ describe('kibanaContextFn', () => { }, }, }, + { + type: 'kibana_query', + language: 'test', + query: { + type: 'test', + match_phrase: { + test: 'something3', + }, + }, + }, { language: 'kuery', query: { diff --git a/src/plugins/data/common/search/expressions/kibana_context.ts b/src/plugins/data/common/search/expressions/kibana_context.ts index 11bbc900c48a6..6183484a57b46 100644 --- a/src/plugins/data/common/search/expressions/kibana_context.ts +++ b/src/plugins/data/common/search/expressions/kibana_context.ts @@ -24,7 +24,7 @@ export interface KibanaContextStartDependencies { } interface Arguments { - q?: KibanaQueryOutput | null; + q?: KibanaQueryOutput[] | null; filters?: KibanaFilter[] | null; timeRange?: KibanaTimerangeOutput | null; savedSearchId?: string | null; @@ -62,8 +62,8 @@ export const getKibanaContextFn = ( args: { q: { types: ['kibana_query', 'null'], + multi: true, aliases: ['query', '_'], - default: null, help: i18n.translate('data.search.functions.kibana_context.q.help', { defaultMessage: 'Specify Kibana free form text query', }), @@ -123,7 +123,7 @@ export const getKibanaContextFn = ( const { savedObjectsClient } = await getStartDependencies(getKibanaRequest); const timeRange = args.timeRange || input?.timeRange; - let queries = mergeQueries(input?.query, args?.q || []); + let queries = mergeQueries(input?.query, args?.q?.filter(Boolean) || []); let filters = [ ...(input?.filters || []), ...((args?.filters?.map(unboxExpressionValue) || []) as Filter[]), diff --git a/src/plugins/data/common/search/search_source/create_search_source.test.ts b/src/plugins/data/common/search/search_source/create_search_source.test.ts index b609d911dc44a..c67e8a21b4f9a 100644 --- a/src/plugins/data/common/search/search_source/create_search_source.test.ts +++ b/src/plugins/data/common/search/search_source/create_search_source.test.ts @@ -19,6 +19,7 @@ describe('createSearchSource', () => { beforeEach(() => { dependencies = { + aggs: {} as SearchSourceDependencies['aggs'], getConfig: jest.fn(), search: jest.fn(), onResponse: (req, res) => res, diff --git a/src/plugins/data/common/search/search_source/mocks.ts b/src/plugins/data/common/search/search_source/mocks.ts index eb10855460236..17b7235d9ccc6 100644 --- a/src/plugins/data/common/search/search_source/mocks.ts +++ b/src/plugins/data/common/search/search_source/mocks.ts @@ -10,7 +10,7 @@ import { of } from 'rxjs'; import type { MockedKeys } from '@kbn/utility-types/jest'; import { uiSettingsServiceMock } from '@kbn/core/public/mocks'; -import { SearchSource } from './search_source'; +import { SearchSource, SearchSourceDependencies } from './search_source'; import { ISearchStartSearchSource, ISearchSource, SearchSourceFields } from './types'; export const searchSourceInstanceMock: MockedKeys = { @@ -35,6 +35,7 @@ export const searchSourceInstanceMock: MockedKeys = { history: [], getSerializedFields: jest.fn(), serialize: jest.fn(), + toExpressionAst: jest.fn(), }; export const searchSourceCommonMock: jest.Mocked = { @@ -48,6 +49,9 @@ export const searchSourceCommonMock: jest.Mocked = { export const createSearchSourceMock = (fields?: SearchSourceFields, response?: any) => new SearchSource(fields, { + aggs: { + createAggConfigs: jest.fn(), + } as unknown as SearchSourceDependencies['aggs'], getConfig: uiSettingsServiceMock.createStartContract().get, search: jest.fn().mockReturnValue( of( diff --git a/src/plugins/data/common/search/search_source/search_source.test.ts b/src/plugins/data/common/search/search_source/search_source.test.ts index 55195902c2e98..044c6414f96e6 100644 --- a/src/plugins/data/common/search/search_source/search_source.test.ts +++ b/src/plugins/data/common/search/search_source/search_source.test.ts @@ -8,12 +8,15 @@ import { lastValueFrom, of, throwError } from 'rxjs'; import type { DataView } from '@kbn/data-views-plugin/common'; +import { buildExpression, ExpressionAstExpression } from '@kbn/expressions-plugin/common'; +import type { MockedKeys } from '@kbn/utility-types/jest'; import { SearchSource, SearchSourceDependencies, SortDirection } from '.'; import { AggConfigs, AggTypesRegistryStart } from '../..'; import { mockAggTypesRegistry } from '../aggs/test_helpers'; import { RequestResponder } from '@kbn/inspector-plugin/common'; import { switchMap } from 'rxjs/operators'; import { Filter } from '@kbn/es-query'; +import { stubIndexPattern } from '../../stubs'; const getComputedFields = () => ({ storedFields: [], @@ -26,6 +29,7 @@ const mockSource = { excludes: ['foo-*'] }; const mockSource2 = { excludes: ['bar-*'] }; const indexPattern = { + id: '1234', title: 'foo', fields: [{ name: 'foo-bar' }, { name: 'field1' }, { name: 'field2' }, { name: '_id' }], getComputedFields, @@ -62,10 +66,13 @@ const runtimeFieldDef = { describe('SearchSource', () => { let mockSearchMethod: any; - let searchSourceDependencies: SearchSourceDependencies; + let searchSourceDependencies: MockedKeys; let searchSource: SearchSource; beforeEach(() => { + const aggsMock = { + createAggConfigs: jest.fn(), + } as unknown as jest.Mocked; const getConfigMock = jest .fn() .mockImplementation((param) => param === 'metaFields' && ['_type', '_source', '_id']) @@ -81,6 +88,7 @@ describe('SearchSource', () => { ); searchSourceDependencies = { + aggs: aggsMock, getConfig: getConfigMock, search: mockSearchMethod, onResponse: (req, res) => res, @@ -1309,4 +1317,145 @@ describe('SearchSource', () => { }); }); }); + + describe('#toExpressionAst()', () => { + function toString(ast: ExpressionAstExpression) { + return buildExpression(ast).toString(); + } + + test('should generate an expression AST', () => { + expect(toString(searchSource.toExpressionAst())).toMatchInlineSnapshot(` + "kibana_context + | esdsl dsl=\\"{}\\"" + `); + }); + + test('should generate query argument', () => { + searchSource.setField('query', { language: 'kuery', query: 'something' }); + + expect(toString(searchSource.toExpressionAst())).toMatchInlineSnapshot(` + "kibana_context q={kql q=\\"something\\"} + | esdsl dsl=\\"{}\\"" + `); + }); + + test('should generate filters argument', () => { + const filter1 = { + query: { query_string: { query: 'query1' } }, + meta: {}, + }; + const filter2 = { + query: { query_string: { query: 'query2' } }, + meta: {}, + }; + searchSource.setField('filter', [filter1, filter2]); + + expect(toString(searchSource.toExpressionAst())).toMatchInlineSnapshot(` + "kibana_context filters={kibanaFilter query=\\"{\\\\\\"query_string\\\\\\":{\\\\\\"query\\\\\\":\\\\\\"query1\\\\\\"}}\\"} + filters={kibanaFilter query=\\"{\\\\\\"query_string\\\\\\":{\\\\\\"query\\\\\\":\\\\\\"query2\\\\\\"}}\\"} + | esdsl dsl=\\"{}\\"" + `); + }); + + test('should resolve filters if set as a function', () => { + const filter = { + query: { query_string: { query: 'query' } }, + meta: {}, + }; + searchSource.setField('filter', () => filter); + + expect(toString(searchSource.toExpressionAst())).toMatchInlineSnapshot(` + "kibana_context filters={kibanaFilter query=\\"{\\\\\\"query_string\\\\\\":{\\\\\\"query\\\\\\":\\\\\\"query\\\\\\"}}\\"} + | esdsl dsl=\\"{}\\"" + `); + }); + + test('should merge properties from parent search sources', () => { + const filter1 = { + query: { query_string: { query: 'query1' } }, + meta: {}, + }; + const filter2 = { + query: { query_string: { query: 'query2' } }, + meta: {}, + }; + searchSource.setField('query', { language: 'kuery', query: 'something1' }); + searchSource.setField('filter', filter1); + + const childSearchSource = searchSource.createChild(); + childSearchSource.setField('query', { language: 'kuery', query: 'something2' }); + childSearchSource.setField('filter', filter2); + + expect(toString(childSearchSource.toExpressionAst())).toMatchInlineSnapshot(` + "kibana_context q={kql q=\\"something2\\"} q={kql q=\\"something1\\"} filters={kibanaFilter query=\\"{\\\\\\"query_string\\\\\\":{\\\\\\"query\\\\\\":\\\\\\"query2\\\\\\"}}\\"} + filters={kibanaFilter query=\\"{\\\\\\"query_string\\\\\\":{\\\\\\"query\\\\\\":\\\\\\"query1\\\\\\"}}\\"} + | esdsl dsl=\\"{}\\"" + `); + }); + + test('should include a data view identifier', () => { + searchSource.setField('index', indexPattern); + + expect(toString(searchSource.toExpressionAst())).toMatchInlineSnapshot(` + "kibana_context + | esdsl dsl=\\"{}\\" index=\\"1234\\"" + `); + }); + + test('should include size if present', () => { + searchSource.setField('size', 1000); + + expect(toString(searchSource.toExpressionAst())).toMatchInlineSnapshot(` + "kibana_context + | esdsl size=1000 dsl=\\"{}\\"" + `); + }); + + test('should generate the `esaggs` function if there are aggregations', () => { + const typesRegistry = mockAggTypesRegistry(); + const aggConfigs = new AggConfigs( + stubIndexPattern, + [{ enabled: true, type: 'avg', schema: 'metric', params: { field: 'bytes' } }], + { typesRegistry } + ); + searchSource.setField('aggs', aggConfigs); + + expect(toString(searchSource.toExpressionAst())).toMatchInlineSnapshot(` + "kibana_context + | esaggs index={indexPatternLoad id=\\"logstash-*\\"} aggs={aggAvg field=\\"bytes\\" id=\\"1\\" enabled=true schema=\\"metric\\"}" + `); + }); + + test('should generate the `esaggs` function if there are aggregations configs', () => { + const typesRegistry = mockAggTypesRegistry(); + searchSourceDependencies.aggs.createAggConfigs.mockImplementationOnce( + (dataView, configs) => new AggConfigs(dataView, configs, { typesRegistry }) + ); + searchSource.setField('index', stubIndexPattern); + searchSource.setField('aggs', [ + { enabled: true, type: 'avg', schema: 'metric', params: { field: 'bytes' } }, + ]); + + expect(toString(searchSource.toExpressionAst())).toMatchInlineSnapshot(` + "kibana_context + | esaggs index={indexPatternLoad id=\\"logstash-*\\"} aggs={aggAvg field=\\"bytes\\" id=\\"1\\" enabled=true schema=\\"metric\\"}" + `); + }); + + test('should not include the `esdsl` function to the chain if the `asDatatable` option is false', () => { + expect(toString(searchSource.toExpressionAst({ asDatatable: false }))).toMatchInlineSnapshot( + `"kibana_context"` + ); + }); + + test('should not include the `esaggs` function to the chain if the `asDatatable` option is false', () => { + searchSource.setField('aggs', [ + { enabled: true, type: 'avg', schema: 'metric', params: { field: 'bytes' } }, + ]); + + expect(toString(searchSource.toExpressionAst({ asDatatable: false }))).toMatchInlineSnapshot( + `"kibana_context"` + ); + }); + }); }); diff --git a/src/plugins/data/common/search/search_source/search_source.ts b/src/plugins/data/common/search/search_source/search_source.ts index d3829781b6512..cd22127ca2fd7 100644 --- a/src/plugins/data/common/search/search_source/search_source.ts +++ b/src/plugins/data/common/search/search_source/search_source.ts @@ -76,6 +76,11 @@ import { buildEsQuery, Filter } from '@kbn/es-query'; import { fieldWildcardFilter } from '@kbn/kibana-utils-plugin/common'; import { getHighlightRequest } from '@kbn/field-formats-plugin/common'; import type { DataView } from '@kbn/data-views-plugin/common'; +import { + ExpressionAstExpression, + buildExpression, + buildExpressionFunction, +} from '@kbn/expressions-plugin/common'; import { normalizeSortRequest } from './normalize_sort_request'; import { AggConfigSerialized, DataViewField, SerializedSearchSourceFields } from '../..'; @@ -104,7 +109,14 @@ import { isPartialResponse, UI_SETTINGS, } from '../..'; +import { AggsStart } from '../aggs'; import { extractReferences } from './extract_references'; +import { + EsdslExpressionFunctionDefinition, + ExpressionFunctionKibanaContext, + filtersToAst, + queryToAst, +} from '../expressions'; /** @internal */ export const searchSourceRequiredUiSettings = [ @@ -122,9 +134,19 @@ export const searchSourceRequiredUiSettings = [ ]; export interface SearchSourceDependencies extends FetchHandlers { + aggs: AggsStart; search: ISearchGeneric; } +interface ExpressionAstOptions { + /** + * When truthy, it will include either `esaggs` or `esdsl` function to the expression chain. + * In this case, the expression will perform a search and return the `datatable` structure. + * @default true + */ + asDatatable?: boolean; +} + /** @public **/ export class SearchSource { private id: string = uniqueId('data_source'); @@ -922,4 +944,54 @@ export class SearchSource { return [filterField]; } + + /** + * Generates an expression abstract syntax tree using the fields set in the current search source and its ancestors. + * The produced expression from the returned AST will return the `datatable` structure. + * If the `asDatatable` option is truthy or omitted, the generator will use the `esdsl` function to perform the search. + * When the `aggs` field is present, it will use the `esaggs` function instead. + * @returns The expression AST. + */ + toExpressionAst({ asDatatable = true }: ExpressionAstOptions = {}): ExpressionAstExpression { + const searchRequest = this.mergeProps(); + const { body, index, query } = searchRequest; + + const filters = ( + typeof searchRequest.filters === 'function' ? searchRequest.filters() : searchRequest.filters + ) as Filter[] | Filter | undefined; + const ast = buildExpression([ + buildExpressionFunction('kibana_context', { + q: query?.map(queryToAst), + filters: filters && filtersToAst(filters), + }), + ]).toAst(); + + if (!asDatatable) { + return ast; + } + + const aggsField = this.getField('aggs'); + const aggs = (typeof aggsField === 'function' ? aggsField() : aggsField) as + | AggConfigs + | AggConfigSerialized[] + | undefined; + const aggConfigs = + aggs instanceof AggConfigs + ? aggs + : index && aggs && this.dependencies.aggs.createAggConfigs(index, aggs); + + if (aggConfigs) { + ast.chain.push(...aggConfigs.toExpressionAst().chain); + } else { + ast.chain.push( + buildExpressionFunction('esdsl', { + size: body?.size, + dsl: JSON.stringify({}), + index: index?.id, + }).toAst() + ); + } + + return ast; + } } diff --git a/src/plugins/data/common/search/search_source/search_source_service.test.ts b/src/plugins/data/common/search/search_source/search_source_service.test.ts index b76a65f7eaf6b..70448db335a07 100644 --- a/src/plugins/data/common/search/search_source/search_source_service.test.ts +++ b/src/plugins/data/common/search/search_source/search_source_service.test.ts @@ -15,6 +15,7 @@ describe('SearchSource service', () => { beforeEach(() => { jest.resetModules(); dependencies = { + aggs: {} as SearchSourceDependencies['aggs'], getConfig: jest.fn(), search: jest.fn(), onResponse: jest.fn(), diff --git a/src/plugins/data/public/search/expressions/esaggs.test.ts b/src/plugins/data/public/search/expressions/esaggs.test.ts index 60037f07fbbbf..33d2ab4a3c1b3 100644 --- a/src/plugins/data/public/search/expressions/esaggs.test.ts +++ b/src/plugins/data/public/search/expressions/esaggs.test.ts @@ -112,11 +112,11 @@ describe('esaggs expression function - public', () => { aggs: { foo: 'bar', hierarchical: true, + partialRows: args.partialRows, }, filters: undefined, indexPattern: {}, inspectorAdapters: mockHandlers.inspectorAdapters, - partialRows: args.partialRows, query: undefined, searchSessionId: 'abc123', searchSourceService: startDependencies.searchSource, diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index ffdd1663a87b1..342abc854138e 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -46,6 +46,7 @@ export function getFunctionDefinition({ args.aggs?.map((agg) => agg.value) ?? [] ); aggConfigs.hierarchical = args.metricsAtAllLevels; + aggConfigs.partialRows = args.partialRows; const { handleEsaggsRequest } = await import('../../../common/search/expressions'); @@ -58,7 +59,6 @@ export function getFunctionDefinition({ filters: get(input, 'filters', undefined), indexPattern, inspectorAdapters, - partialRows: args.partialRows, query: get(input, 'query', undefined) as any, searchSessionId: getSearchSessionId(), searchSourceService: searchSource, diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index cc6fa7e509327..6c7ec3af0f0d7 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -231,7 +231,9 @@ export class SearchService implements Plugin { const loadingCount$ = new BehaviorSubject(0); http.addLoadingCountSource(loadingCount$); + const aggs = this.aggsService.start({ fieldFormats, uiSettings, indexPatterns }); const searchSourceDependencies: SearchSourceDependencies = { + aggs, getConfig: uiSettings.get.bind(uiSettings), search, onResponse: (request: SearchRequest, response: IKibanaSearchResponse) => @@ -261,7 +263,7 @@ export class SearchService implements Plugin { } return { - aggs: this.aggsService.start({ fieldFormats, uiSettings, indexPatterns }), + aggs, search, showError: (e: Error) => { this.searchInterceptor.showError(e); diff --git a/src/plugins/data/server/search/expressions/esaggs.test.ts b/src/plugins/data/server/search/expressions/esaggs.test.ts index 287a10204cac8..f5042b05ea9f4 100644 --- a/src/plugins/data/server/search/expressions/esaggs.test.ts +++ b/src/plugins/data/server/search/expressions/esaggs.test.ts @@ -120,11 +120,11 @@ describe('esaggs expression function - server', () => { aggs: { foo: 'bar', hierarchical: args.metricsAtAllLevels, + partialRows: args.partialRows, }, filters: undefined, indexPattern: {}, inspectorAdapters: mockHandlers.inspectorAdapters, - partialRows: args.partialRows, query: undefined, searchSessionId: 'abc123', searchSourceService: startDependencies.searchSource, diff --git a/src/plugins/data/server/search/expressions/esaggs.ts b/src/plugins/data/server/search/expressions/esaggs.ts index 25006d8b20d85..bca2ac63b7f0f 100644 --- a/src/plugins/data/server/search/expressions/esaggs.ts +++ b/src/plugins/data/server/search/expressions/esaggs.ts @@ -60,6 +60,7 @@ export function getFunctionDefinition({ ); aggConfigs.hierarchical = args.metricsAtAllLevels; + aggConfigs.partialRows = args.partialRows; return { aggConfigs, indexPattern, searchSource }; }).pipe( @@ -70,7 +71,6 @@ export function getFunctionDefinition({ filters: get(input, 'filters', undefined), indexPattern, inspectorAdapters, - partialRows: args.partialRows, query: get(input, 'query', undefined) as any, searchSessionId: getSearchSessionId(), searchSourceService: searchSource, diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts index 37913461ef640..6561e6e127d0b 100644 --- a/src/plugins/data/server/search/search_service.ts +++ b/src/plugins/data/server/search/search_service.ts @@ -275,13 +275,15 @@ export class SearchService implements Plugin { this.sessionService.start(core, { taskManager }); } + const aggs = this.aggsService.start({ + fieldFormats, + uiSettings, + indexPatterns, + }); + this.asScoped = this.asScopedProvider(core); return { - aggs: this.aggsService.start({ - fieldFormats, - uiSettings, - indexPatterns, - }), + aggs, searchAsInternalUser: this.searchAsInternalUser, getSearchStrategy: this.getSearchStrategy, asScoped: this.asScoped, @@ -294,6 +296,7 @@ export class SearchService implements Plugin { esClient.asCurrentUser ); const uiSettingsClient = uiSettings.asScopedToClient(savedObjectsClient); + const aggsStart = await aggs.asScopedToClient(savedObjectsClient, esClient.asCurrentUser); // cache ui settings, only including items which are explicitly needed by SearchSource const uiSettingsCache = pick( @@ -302,6 +305,7 @@ export class SearchService implements Plugin { ); const searchSourceDependencies: SearchSourceDependencies = { + aggs: aggsStart, getConfig: (key: string): T => uiSettingsCache[key], search: this.asScoped(request).search, onResponse: (req, res) => res, diff --git a/src/plugins/discover/public/services/saved_searches/get_saved_searches.test.ts b/src/plugins/discover/public/services/saved_searches/get_saved_searches.test.ts index 9f9fc86b0288e..3e103d6ea3699 100644 --- a/src/plugins/discover/public/services/saved_searches/get_saved_searches.test.ts +++ b/src/plugins/discover/public/services/saved_searches/get_saved_searches.test.ts @@ -127,6 +127,7 @@ describe('getSavedSearch', () => { "setFields": [MockFunction], "setOverwriteDataViewType": [MockFunction], "setParent": [MockFunction], + "toExpressionAst": [MockFunction], }, "sharingSavedObjectProps": Object { "aliasPurpose": undefined, diff --git a/src/plugins/discover/public/services/saved_searches/saved_searches_utils.test.ts b/src/plugins/discover/public/services/saved_searches/saved_searches_utils.test.ts index 9b42d7557b05c..f0958737d3b79 100644 --- a/src/plugins/discover/public/services/saved_searches/saved_searches_utils.test.ts +++ b/src/plugins/discover/public/services/saved_searches/saved_searches_utils.test.ts @@ -44,6 +44,9 @@ describe('saved_searches_utils', () => { "rowHeight": undefined, "searchSource": SearchSource { "dependencies": Object { + "aggs": Object { + "createAggConfigs": [MockFunction], + }, "getConfig": [MockFunction], "onResponse": [MockFunction], "search": [MockFunction], diff --git a/src/plugins/vis_types/gauge/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_types/gauge/public/__snapshots__/to_ast.test.ts.snap index 73c0ee3e38d7f..79af22ed442a7 100644 --- a/src/plugins/vis_types/gauge/public/__snapshots__/to_ast.test.ts.snap +++ b/src/plugins/vis_types/gauge/public/__snapshots__/to_ast.test.ts.snap @@ -3,35 +3,6 @@ exports[`gauge vis toExpressionAst function with minimal params 1`] = ` Object { "chain": Array [ - Object { - "arguments": Object { - "aggs": Array [], - "index": Array [ - Object { - "chain": Array [ - Object { - "arguments": Object { - "id": Array [ - "123", - ], - }, - "function": "indexPatternLoad", - "type": "function", - }, - ], - "type": "expression", - }, - ], - "metricsAtAllLevels": Array [ - false, - ], - "partialRows": Array [ - false, - ], - }, - "function": "esaggs", - "type": "function", - }, Object { "arguments": Object { "centralMajorMode": Array [ diff --git a/src/plugins/vis_types/gauge/public/to_ast.test.ts b/src/plugins/vis_types/gauge/public/to_ast.test.ts index f3b8ee90b5b55..f88743dd70b2c 100644 --- a/src/plugins/vis_types/gauge/public/to_ast.test.ts +++ b/src/plugins/vis_types/gauge/public/to_ast.test.ts @@ -34,13 +34,7 @@ describe('gauge vis toExpressionAst function', () => { }, }, }, - data: { - indexPattern: { id: '123' } as any, - aggs: { - getResponseAggs: () => [], - aggs: [], - } as any, - }, + data: {}, } as unknown as Vis; }); diff --git a/src/plugins/vis_types/gauge/public/to_ast.ts b/src/plugins/vis_types/gauge/public/to_ast.ts index 85148b713b319..697b9790468a3 100644 --- a/src/plugins/vis_types/gauge/public/to_ast.ts +++ b/src/plugins/vis_types/gauge/public/to_ast.ts @@ -14,7 +14,6 @@ import type { } from '@kbn/expression-gauge-plugin/common'; import { GaugeType, GaugeVisParams } from './types'; import { getStopsWithColorsFromRanges } from './utils'; -import { getEsaggsFn } from './to_ast_esaggs'; const prepareDimension = (params: SchemaConfig) => { const visdimension = buildExpressionFunction('visdimension', { accessor: params.accessor }); @@ -90,7 +89,7 @@ export const toExpressionAst: VisToExpressionAst = (vis, params) gauge.addArgument('palette', buildExpression([palette])); } - const ast = buildExpression([getEsaggsFn(vis), gauge]); + const ast = buildExpression([gauge]); return ast.toAst(); }; diff --git a/src/plugins/vis_types/gauge/public/to_ast_esaggs.ts b/src/plugins/vis_types/gauge/public/to_ast_esaggs.ts deleted file mode 100644 index 4b098342c6de2..0000000000000 --- a/src/plugins/vis_types/gauge/public/to_ast_esaggs.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 { Vis } from '@kbn/visualizations-plugin/public'; -import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; -import { - EsaggsExpressionFunctionDefinition, - IndexPatternLoadExpressionFunctionDefinition, -} from '@kbn/data-plugin/public'; - -import { GaugeVisParams } from './types'; - -/** - * Get esaggs expressions function - * @param vis - */ -export function getEsaggsFn(vis: Vis) { - return buildExpressionFunction('esaggs', { - index: buildExpression([ - buildExpressionFunction('indexPatternLoad', { - id: vis.data.indexPattern!.id!, - }), - ]), - metricsAtAllLevels: vis.isHierarchical(), - partialRows: false, - aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), - }); -} diff --git a/src/plugins/vis_types/gauge/public/vis_type/gauge.tsx b/src/plugins/vis_types/gauge/public/vis_type/gauge.tsx index 3de528bfe5e6c..b6bdf93a8ea89 100644 --- a/src/plugins/vis_types/gauge/public/vis_type/gauge.tsx +++ b/src/plugins/vis_types/gauge/public/vis_type/gauge.tsx @@ -29,6 +29,7 @@ export const getGaugeVisTypeDefinition = ( defaultMessage: 'Show the status of a metric.', }), getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter], + fetchDatatable: true, toExpressionAst, visConfig: { defaults: { diff --git a/src/plugins/vis_types/gauge/public/vis_type/goal.tsx b/src/plugins/vis_types/gauge/public/vis_type/goal.tsx index c953cd3e5dfe2..bcf7596094cd1 100644 --- a/src/plugins/vis_types/gauge/public/vis_type/goal.tsx +++ b/src/plugins/vis_types/gauge/public/vis_type/goal.tsx @@ -27,6 +27,7 @@ export const getGoalVisTypeDefinition = ( description: i18n.translate('visTypeGauge.goal.goalDescription', { defaultMessage: 'Track how a metric progresses to a goal.', }), + fetchDatatable: true, toExpressionAst, visConfig: { defaults: { diff --git a/src/plugins/vis_types/heatmap/public/to_ast.test.ts b/src/plugins/vis_types/heatmap/public/to_ast.test.ts index 8c7e3372df867..d1e312755cf49 100644 --- a/src/plugins/vis_types/heatmap/public/to_ast.test.ts +++ b/src/plugins/vis_types/heatmap/public/to_ast.test.ts @@ -23,10 +23,6 @@ jest.mock('@kbn/expressions-plugin/public', () => ({ })), })); -jest.mock('./to_ast_esaggs', () => ({ - getEsaggsFn: jest.fn(), -})); - describe('heatmap vis toExpressionAst function', () => { let vis: Vis; @@ -42,7 +38,7 @@ describe('heatmap vis toExpressionAst function', () => { it('should match basic snapshot', () => { toExpressionAst(vis, params); - const [, builtExpression] = (buildExpression as jest.Mock).mock.calls.pop()[0]; + const [builtExpression] = (buildExpression as jest.Mock).mock.calls.pop()[0]; expect(builtExpression).toMatchSnapshot(); }); diff --git a/src/plugins/vis_types/heatmap/public/to_ast.ts b/src/plugins/vis_types/heatmap/public/to_ast.ts index 5b52ab1feeb3a..a5a14f5412dca 100644 --- a/src/plugins/vis_types/heatmap/public/to_ast.ts +++ b/src/plugins/vis_types/heatmap/public/to_ast.ts @@ -10,7 +10,6 @@ import { VisToExpressionAst, getVisSchemas, SchemaConfig } from '@kbn/visualizat import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; import { getStopsWithColorsFromRanges, getStopsWithColorsFromColorsNumber } from './utils/palette'; import type { HeatmapVisParams } from './types'; -import { getEsaggsFn } from './to_ast_esaggs'; const DEFAULT_PERCENT_DECIMALS = 2; @@ -127,7 +126,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, } visTypeHeatmap.addArgument('palette', buildExpression([palette])); - const ast = buildExpression([getEsaggsFn(vis), visTypeHeatmap]); + const ast = buildExpression([visTypeHeatmap]); return ast.toAst(); }; diff --git a/src/plugins/vis_types/heatmap/public/to_ast_esaggs.ts b/src/plugins/vis_types/heatmap/public/to_ast_esaggs.ts deleted file mode 100644 index 7a95c59646f45..0000000000000 --- a/src/plugins/vis_types/heatmap/public/to_ast_esaggs.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 { Vis } from '@kbn/visualizations-plugin/public'; -import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; -import { - EsaggsExpressionFunctionDefinition, - IndexPatternLoadExpressionFunctionDefinition, -} from '@kbn/data-plugin/public'; - -import { HeatmapVisParams } from './types'; - -/** - * Get esaggs expressions function - * @param vis - */ -export function getEsaggsFn(vis: Vis) { - return buildExpressionFunction('esaggs', { - index: buildExpression([ - buildExpressionFunction('indexPatternLoad', { - id: vis.data.indexPattern!.id!, - }), - ]), - metricsAtAllLevels: vis.isHierarchical(), - partialRows: false, - aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), - }); -} diff --git a/src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx b/src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx index 6f711eb2667df..ee2893f2cb190 100644 --- a/src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx +++ b/src/plugins/vis_types/heatmap/public/vis_type/heatmap.tsx @@ -28,6 +28,7 @@ export const getHeatmapVisTypeDefinition = ({ description: i18n.translate('visTypeHeatmap.heatmap.heatmapDescription', { defaultMessage: 'Display values as colors in a matrix.', }), + fetchDatatable: true, toExpressionAst, getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter], visConfig: { diff --git a/src/plugins/vis_types/metric/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_types/metric/public/__snapshots__/to_ast.test.ts.snap index ef6102571f324..b64b14bd09035 100644 --- a/src/plugins/vis_types/metric/public/__snapshots__/to_ast.test.ts.snap +++ b/src/plugins/vis_types/metric/public/__snapshots__/to_ast.test.ts.snap @@ -3,35 +3,6 @@ exports[`metric vis toExpressionAst function with percentage mode should have percentage format 1`] = ` Object { "chain": Array [ - Object { - "arguments": Object { - "aggs": Array [], - "index": Array [ - Object { - "chain": Array [ - Object { - "arguments": Object { - "id": Array [ - "123", - ], - }, - "function": "indexPatternLoad", - "type": "function", - }, - ], - "type": "expression", - }, - ], - "metricsAtAllLevels": Array [ - false, - ], - "partialRows": Array [ - false, - ], - }, - "function": "esaggs", - "type": "function", - }, Object { "arguments": Object { "font": Array [ @@ -96,35 +67,6 @@ Object { exports[`metric vis toExpressionAst function without params 1`] = ` Object { "chain": Array [ - Object { - "arguments": Object { - "aggs": Array [], - "index": Array [ - Object { - "chain": Array [ - Object { - "arguments": Object { - "id": Array [ - "123", - ], - }, - "function": "indexPatternLoad", - "type": "function", - }, - ], - "type": "expression", - }, - ], - "metricsAtAllLevels": Array [ - false, - ], - "partialRows": Array [ - false, - ], - }, - "function": "esaggs", - "type": "function", - }, Object { "arguments": Object { "font": Array [ diff --git a/src/plugins/vis_types/metric/public/metric_vis_type.ts b/src/plugins/vis_types/metric/public/metric_vis_type.ts index 15ec40d3bd612..30e13e8605b6d 100644 --- a/src/plugins/vis_types/metric/public/metric_vis_type.ts +++ b/src/plugins/vis_types/metric/public/metric_vis_type.ts @@ -21,6 +21,7 @@ export const createMetricVisTypeDefinition = (): VisTypeDefinition => description: i18n.translate('visTypeMetric.metricDescription', { defaultMessage: 'Show a calculation as a single number.', }), + fetchDatatable: true, toExpressionAst, visConfig: { defaults: { diff --git a/src/plugins/vis_types/metric/public/to_ast.test.ts b/src/plugins/vis_types/metric/public/to_ast.test.ts index bb9a5f0873f11..3c6ba5c532701 100644 --- a/src/plugins/vis_types/metric/public/to_ast.test.ts +++ b/src/plugins/vis_types/metric/public/to_ast.test.ts @@ -22,13 +22,7 @@ describe('metric vis toExpressionAst function', () => { params: { percentageMode: false, }, - data: { - indexPattern: { id: '123' } as any, - aggs: { - getResponseAggs: () => [], - aggs: [], - } as any, - }, + data: {}, } as unknown as Vis; }); diff --git a/src/plugins/vis_types/metric/public/to_ast.ts b/src/plugins/vis_types/metric/public/to_ast.ts index d206d046cde6a..7b771a811ba68 100644 --- a/src/plugins/vis_types/metric/public/to_ast.ts +++ b/src/plugins/vis_types/metric/public/to_ast.ts @@ -11,10 +11,6 @@ import { getVisSchemas, SchemaConfig, VisToExpressionAst } from '@kbn/visualizat import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; import { inter } from '@kbn/expressions-plugin/common'; -import { - EsaggsExpressionFunctionDefinition, - IndexPatternLoadExpressionFunctionDefinition, -} from '@kbn/data-plugin/public'; import { VisParams } from './types'; import { getStopsWithColorsFromRanges } from './utils'; @@ -30,17 +26,6 @@ const prepareDimension = (params: SchemaConfig) => { }; export const toExpressionAst: VisToExpressionAst = (vis, params) => { - const esaggs = buildExpressionFunction('esaggs', { - index: buildExpression([ - buildExpressionFunction('indexPatternLoad', { - id: vis.data.indexPattern!.id!, - }), - ]), - metricsAtAllLevels: vis.isHierarchical(), - partialRows: false, - aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), - }); - const schemas = getVisSchemas(vis, params); const { @@ -75,7 +60,7 @@ export const toExpressionAst: VisToExpressionAst = (vis, params) => { metricVis.addArgument( 'font', buildExpression( - `font family="${inter.value}" + `font family="${inter.value}" weight="bold" align="center" sizeUnit="pt" @@ -104,7 +89,7 @@ export const toExpressionAst: VisToExpressionAst = (vis, params) => { metricVis.addArgument('metric', prepareDimension(metric)); }); - const ast = buildExpression([esaggs, metricVis]); + const ast = buildExpression([metricVis]); return ast.toAst(); }; diff --git a/src/plugins/vis_types/pie/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_types/pie/public/__snapshots__/to_ast.test.ts.snap index 5b8bd613609f9..b9dcb3f6bff6a 100644 --- a/src/plugins/vis_types/pie/public/__snapshots__/to_ast.test.ts.snap +++ b/src/plugins/vis_types/pie/public/__snapshots__/to_ast.test.ts.snap @@ -3,35 +3,6 @@ exports[`vis type pie vis toExpressionAst function should match basic snapshot 1`] = ` Object { "chain": Array [ - Object { - "arguments": Object { - "aggs": Array [], - "index": Array [ - Object { - "chain": Array [ - Object { - "arguments": Object { - "id": Array [ - "123", - ], - }, - "function": "indexPatternLoad", - "type": "function", - }, - ], - "type": "expression", - }, - ], - "metricsAtAllLevels": Array [ - true, - ], - "partialRows": Array [ - false, - ], - }, - "function": "esaggs", - "type": "function", - }, Object { "arguments": Object { "addTooltip": Array [ diff --git a/src/plugins/vis_types/pie/public/to_ast.ts b/src/plugins/vis_types/pie/public/to_ast.ts index 7a131dbb76b9c..91ff6b0b6c17d 100644 --- a/src/plugins/vis_types/pie/public/to_ast.ts +++ b/src/plugins/vis_types/pie/public/to_ast.ts @@ -16,7 +16,6 @@ import { PartitionVisParams, LabelsParams, } from '@kbn/expression-partition-vis-plugin/common'; -import { getEsaggsFn } from './to_ast_esaggs'; const prepareDimension = (params: SchemaConfig) => { const visdimension = buildExpressionFunction('visdimension', { accessor: params.accessor }); @@ -83,7 +82,7 @@ export const toExpressionAst: VisToExpressionAst = async (vi args ); - const ast = buildExpression([getEsaggsFn(vis), visTypePie]); + const ast = buildExpression([visTypePie]); return ast.toAst(); }; diff --git a/src/plugins/vis_types/pie/public/to_ast_esaggs.ts b/src/plugins/vis_types/pie/public/to_ast_esaggs.ts deleted file mode 100644 index ed689d065d66c..0000000000000 --- a/src/plugins/vis_types/pie/public/to_ast_esaggs.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 { Vis } from '@kbn/visualizations-plugin/public'; -import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; -import { - EsaggsExpressionFunctionDefinition, - IndexPatternLoadExpressionFunctionDefinition, -} from '@kbn/data-plugin/public'; -import { PartitionVisParams } from '@kbn/expression-partition-vis-plugin/common'; - -/** - * Get esaggs expressions function - * @param vis - */ -export function getEsaggsFn(vis: Vis) { - return buildExpressionFunction('esaggs', { - index: buildExpression([ - buildExpressionFunction('indexPatternLoad', { - id: vis.data.indexPattern!.id!, - }), - ]), - metricsAtAllLevels: vis.isHierarchical(), - partialRows: false, - aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), - }); -} diff --git a/src/plugins/vis_types/pie/public/vis_type/pie.ts b/src/plugins/vis_types/pie/public/vis_type/pie.ts index b23f1b3ac4688..113c277d5e210 100644 --- a/src/plugins/vis_types/pie/public/vis_type/pie.ts +++ b/src/plugins/vis_types/pie/public/vis_type/pie.ts @@ -33,6 +33,7 @@ export const getPieVisTypeDefinition = ({ description: i18n.translate('visTypePie.pie.pieDescription', { defaultMessage: 'Compare data in proportion to a whole.', }), + fetchDatatable: true, toExpressionAst, getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter], visConfig: { diff --git a/src/plugins/vis_types/table/public/table_vis_type.ts b/src/plugins/vis_types/table/public/table_vis_type.ts index b4e7a2274852e..8bd20fb6a0c81 100644 --- a/src/plugins/vis_types/table/public/table_vis_type.ts +++ b/src/plugins/vis_types/table/public/table_vis_type.ts @@ -97,7 +97,9 @@ export const tableVisTypeDefinition: VisTypeDefinition = { }, ], }, + fetchDatatable: true, toExpressionAst, + hasPartialRows: (vis) => vis.params.showPartialRows, hierarchicalData: (vis) => vis.params.showPartialRows || vis.params.showMetricsAtAllLevels, requiresSearch: true, }; diff --git a/src/plugins/vis_types/table/public/to_ast.test.ts b/src/plugins/vis_types/table/public/to_ast.test.ts index da112d94c0c18..fc1ebf28c54c5 100644 --- a/src/plugins/vis_types/table/public/to_ast.test.ts +++ b/src/plugins/vis_types/table/public/to_ast.test.ts @@ -58,13 +58,7 @@ describe('table vis toExpressionAst function', () => { showToolbar: false, totalFunc: AggTypes.SUM, }, - data: { - indexPattern: { id: '123' }, - aggs: { - getResponseAggs: () => [], - aggs: [], - }, - }, + data: {}, } as any; }); @@ -75,53 +69,35 @@ describe('table vis toExpressionAst function', () => { it('should create table expression ast', () => { toExpressionAst(vis, {} as any); - expect((buildExpressionFunction as jest.Mock).mock.calls.length).toEqual(5); - expect((buildExpressionFunction as jest.Mock).mock.calls[0]).toEqual([ - 'indexPatternLoad', - { id: '123' }, - ]); - expect((buildExpressionFunction as jest.Mock).mock.calls[1]).toEqual([ - 'esaggs', - { - index: expect.any(Object), - metricsAtAllLevels: false, - partialRows: true, - aggs: [], - }, - ]); + expect(buildExpressionFunction).toHaveBeenCalledTimes(3); // prepare metrics dimensions - expect((buildExpressionFunction as jest.Mock).mock.calls[2]).toEqual([ - 'visdimension', - { accessor: 1 }, - ]); + expect(buildExpressionFunction).nthCalledWith(1, 'visdimension', { accessor: 1 }); // prepare buckets dimensions - expect((buildExpressionFunction as jest.Mock).mock.calls[3]).toEqual([ - 'visdimension', - { accessor: 0 }, - ]); + expect(buildExpressionFunction).nthCalledWith(2, 'visdimension', { accessor: 0 }); // prepare table expression function - expect((buildExpressionFunction as jest.Mock).mock.calls[4]).toEqual([ - 'kibana_table', - { - buckets: [mockTableExpression], - metrics: [mockTableExpression], - perPage: 20, - percentageCol: 'Count', - row: undefined, - showMetricsAtAllLevels: true, - showPartialRows: true, - showToolbar: false, - showTotal: true, - title: undefined, - totalFunc: 'sum', - }, - ]); + expect(buildExpressionFunction).nthCalledWith(3, 'kibana_table', { + buckets: [mockTableExpression], + metrics: [mockTableExpression], + perPage: 20, + percentageCol: 'Count', + row: undefined, + showMetricsAtAllLevels: true, + showPartialRows: true, + showToolbar: false, + showTotal: true, + title: undefined, + totalFunc: 'sum', + }); }); it('should filter out invalid vis params', () => { // @ts-expect-error vis.params.sort = { columnIndex: null }; toExpressionAst(vis, {} as any); - expect((buildExpressionFunction as jest.Mock).mock.calls[4][1].sort).toBeUndefined(); + expect(buildExpressionFunction).nthCalledWith( + 2, + expect.anything(), + expect.not.objectContaining({ sort: expect.anything() }) + ); }); }); diff --git a/src/plugins/vis_types/table/public/to_ast.ts b/src/plugins/vis_types/table/public/to_ast.ts index ac3799fb51cea..a0149b2ba7e6b 100644 --- a/src/plugins/vis_types/table/public/to_ast.ts +++ b/src/plugins/vis_types/table/public/to_ast.ts @@ -6,10 +6,6 @@ * Side Public License, v 1. */ -import { - EsaggsExpressionFunctionDefinition, - IndexPatternLoadExpressionFunctionDefinition, -} from '@kbn/data-plugin/public'; import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; import { getVisSchemas, SchemaConfig, VisToExpressionAst } from '@kbn/visualizations-plugin/public'; import { TableVisParams } from '../common'; @@ -41,17 +37,6 @@ const getMetrics = (schemas: ReturnType, visParams: TableV }; export const toExpressionAst: VisToExpressionAst = (vis, params) => { - const esaggs = buildExpressionFunction('esaggs', { - index: buildExpression([ - buildExpressionFunction('indexPatternLoad', { - id: vis.data.indexPattern!.id!, - }), - ]), - metricsAtAllLevels: vis.isHierarchical(), - partialRows: vis.params.showPartialRows, - aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), - }); - const schemas = getVisSchemas(vis, params); const metrics = getMetrics(schemas, vis.params); @@ -81,7 +66,7 @@ export const toExpressionAst: VisToExpressionAst = (vis, params) table.addArgument('splitRow', prepareDimension(schemas.split_row[0])); } - const ast = buildExpression([esaggs, table]); + const ast = buildExpression([table]); return ast.toAst(); }; diff --git a/src/plugins/vis_types/tagcloud/public/__snapshots__/to_ast.test.ts.snap b/src/plugins/vis_types/tagcloud/public/__snapshots__/to_ast.test.ts.snap index 3f50cdf559e19..b766feeef5307 100644 --- a/src/plugins/vis_types/tagcloud/public/__snapshots__/to_ast.test.ts.snap +++ b/src/plugins/vis_types/tagcloud/public/__snapshots__/to_ast.test.ts.snap @@ -3,35 +3,6 @@ exports[`tagcloud vis toExpressionAst function should match snapshot params fulfilled with DatatableColumn vis_dimension.accessor at metric 1`] = ` Object { "chain": Array [ - Object { - "arguments": Object { - "aggs": Array [], - "index": Array [ - Object { - "chain": Array [ - Object { - "arguments": Object { - "id": Array [ - "123", - ], - }, - "function": "indexPatternLoad", - "type": "function", - }, - ], - "type": "expression", - }, - ], - "metricsAtAllLevels": Array [ - false, - ], - "partialRows": Array [ - false, - ], - }, - "function": "esaggs", - "type": "function", - }, Object { "arguments": Object { "bucket": Array [ @@ -118,35 +89,6 @@ Object { exports[`tagcloud vis toExpressionAst function should match snapshot params fulfilled with number vis_dimension.accessor at metric 1`] = ` Object { "chain": Array [ - Object { - "arguments": Object { - "aggs": Array [], - "index": Array [ - Object { - "chain": Array [ - Object { - "arguments": Object { - "id": Array [ - "123", - ], - }, - "function": "indexPatternLoad", - "type": "function", - }, - ], - "type": "expression", - }, - ], - "metricsAtAllLevels": Array [ - false, - ], - "partialRows": Array [ - false, - ], - }, - "function": "esaggs", - "type": "function", - }, Object { "arguments": Object { "bucket": Array [ @@ -233,35 +175,6 @@ Object { exports[`tagcloud vis toExpressionAst function should match snapshot without params 1`] = ` Object { "chain": Array [ - Object { - "arguments": Object { - "aggs": Array [], - "index": Array [ - Object { - "chain": Array [ - Object { - "arguments": Object { - "id": Array [ - "123", - ], - }, - "function": "indexPatternLoad", - "type": "function", - }, - ], - "type": "expression", - }, - ], - "metricsAtAllLevels": Array [ - false, - ], - "partialRows": Array [ - false, - ], - }, - "function": "esaggs", - "type": "function", - }, Object { "arguments": Object { "bucket": Array [ diff --git a/src/plugins/vis_types/tagcloud/public/tag_cloud_type.ts b/src/plugins/vis_types/tagcloud/public/tag_cloud_type.ts index 35b7845ec515f..417ec9430333d 100644 --- a/src/plugins/vis_types/tagcloud/public/tag_cloud_type.ts +++ b/src/plugins/vis_types/tagcloud/public/tag_cloud_type.ts @@ -38,6 +38,7 @@ export const getTagCloudVisTypeDefinition = ({ palettes }: TagCloudVisDependenci }, }, }, + fetchDatatable: true, toExpressionAst, editorConfig: { enableDataViewChange: true, diff --git a/src/plugins/vis_types/tagcloud/public/to_ast.test.ts b/src/plugins/vis_types/tagcloud/public/to_ast.test.ts index 2c3fcc5799742..e6c70e36c7089 100644 --- a/src/plugins/vis_types/tagcloud/public/to_ast.test.ts +++ b/src/plugins/vis_types/tagcloud/public/to_ast.test.ts @@ -44,13 +44,7 @@ describe('tagcloud vis toExpressionAst function', () => { params: { showLabel: false, }, - data: { - indexPattern: { id: '123' }, - aggs: { - getResponseAggs: () => [], - aggs: [], - }, - }, + data: {}, } as unknown as Vis; }); diff --git a/src/plugins/vis_types/tagcloud/public/to_ast.ts b/src/plugins/vis_types/tagcloud/public/to_ast.ts index 78461475a3d3d..632a4ceb775a0 100644 --- a/src/plugins/vis_types/tagcloud/public/to_ast.ts +++ b/src/plugins/vis_types/tagcloud/public/to_ast.ts @@ -7,10 +7,6 @@ */ import type { PaletteOutput } from '@kbn/coloring'; -import { - EsaggsExpressionFunctionDefinition, - IndexPatternLoadExpressionFunctionDefinition, -} from '@kbn/data-plugin/public'; import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; import { getVisSchemas, SchemaConfig, VisToExpressionAst } from '@kbn/visualizations-plugin/public'; import { TagCloudVisParams } from './types'; @@ -34,17 +30,6 @@ const preparePalette = (palette?: PaletteOutput) => { }; export const toExpressionAst: VisToExpressionAst = (vis, params) => { - const esaggs = buildExpressionFunction('esaggs', { - index: buildExpression([ - buildExpressionFunction('indexPatternLoad', { - id: vis.data.indexPattern!.id!, - }), - ]), - metricsAtAllLevels: vis.isHierarchical(), - partialRows: false, - aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), - }); - const schemas = getVisSchemas(vis, params); const { scale, orientation, minFontSize, maxFontSize, showLabel, palette } = vis.params; @@ -62,7 +47,7 @@ export const toExpressionAst: VisToExpressionAst = (vis, para tagcloud.addArgument('bucket', prepareDimension(schemas.segment[0])); } - const ast = buildExpression([esaggs, tagcloud]); + const ast = buildExpression([tagcloud]); return ast.toAst(); }; diff --git a/src/plugins/vis_types/vislib/public/to_ast.test.ts b/src/plugins/vis_types/vislib/public/to_ast.test.ts index 1628fb1812d34..a7bbf146005b4 100644 --- a/src/plugins/vis_types/vislib/public/to_ast.test.ts +++ b/src/plugins/vis_types/vislib/public/to_ast.test.ts @@ -23,10 +23,6 @@ jest.mock('@kbn/expressions-plugin/public', () => ({ })), })); -jest.mock('./to_ast_esaggs', () => ({ - getEsaggsFn: jest.fn(), -})); - describe('vislib vis toExpressionAst function', () => { let vis: Vis; @@ -42,7 +38,7 @@ describe('vislib vis toExpressionAst function', () => { it('should match basic snapshot', () => { toExpressionAst(vis, params); - const [, builtExpression] = (buildExpression as jest.Mock).mock.calls[0][0]; + const [builtExpression] = (buildExpression as jest.Mock).mock.calls[0][0]; expect(builtExpression).toMatchSnapshot(); }); diff --git a/src/plugins/vis_types/vislib/public/to_ast.ts b/src/plugins/vis_types/vislib/public/to_ast.ts index 6ef3ec72f4ab0..ceb938d5d72e1 100644 --- a/src/plugins/vis_types/vislib/public/to_ast.ts +++ b/src/plugins/vis_types/vislib/public/to_ast.ts @@ -22,7 +22,6 @@ import { BUCKET_TYPES } from '@kbn/data-plugin/public'; import { vislibVisName, VisTypeVislibExpressionFunctionDefinition } from './vis_type_vislib_vis_fn'; import { BasicVislibParams, VislibChartType } from './types'; -import { getEsaggsFn } from './to_ast_esaggs'; export const toExpressionAst = async ( vis: Vis, @@ -95,7 +94,7 @@ export const toExpressionAst = async ( } ); - const ast = buildExpression([getEsaggsFn(vis), visTypeVislib]); + const ast = buildExpression([visTypeVislib]); return ast.toAst(); }; diff --git a/src/plugins/vis_types/vislib/public/to_ast_esaggs.ts b/src/plugins/vis_types/vislib/public/to_ast_esaggs.ts deleted file mode 100644 index 6874f812c41ff..0000000000000 --- a/src/plugins/vis_types/vislib/public/to_ast_esaggs.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 { Vis } from '@kbn/visualizations-plugin/public'; -import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; -import { - EsaggsExpressionFunctionDefinition, - IndexPatternLoadExpressionFunctionDefinition, -} from '@kbn/data-plugin/public'; - -/** - * Get esaggs expressions function - * TODO: replace this with vis.data.aggs!.toExpressionAst(); - * https://github.com/elastic/kibana/issues/61768 - * @param vis - */ -export function getEsaggsFn(vis: Vis) { - return buildExpressionFunction('esaggs', { - index: buildExpression([ - buildExpressionFunction('indexPatternLoad', { - id: vis.data.indexPattern!.id!, - }), - ]), - metricsAtAllLevels: vis.isHierarchical(), - partialRows: false, - aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), - }); -} diff --git a/src/plugins/vis_types/vislib/public/to_ast_pie.test.ts b/src/plugins/vis_types/vislib/public/to_ast_pie.test.ts index 49a44c3de4a89..9cb57c8086db1 100644 --- a/src/plugins/vis_types/vislib/public/to_ast_pie.test.ts +++ b/src/plugins/vis_types/vislib/public/to_ast_pie.test.ts @@ -23,10 +23,6 @@ jest.mock('@kbn/expressions-plugin/public', () => ({ })), })); -jest.mock('./to_ast_esaggs', () => ({ - getEsaggsFn: jest.fn(), -})); - describe('vislib pie vis toExpressionAst function', () => { let vis: Vis; @@ -42,7 +38,7 @@ describe('vislib pie vis toExpressionAst function', () => { it('should match basic snapshot', () => { toExpressionAst(vis, params); - const [, builtExpression] = (buildExpression as jest.Mock).mock.calls[0][0]; + const [builtExpression] = (buildExpression as jest.Mock).mock.calls[0][0]; expect(builtExpression).toMatchSnapshot(); }); diff --git a/src/plugins/vis_types/vislib/public/to_ast_pie.ts b/src/plugins/vis_types/vislib/public/to_ast_pie.ts index 9f7bda7740a44..3302130df0134 100644 --- a/src/plugins/vis_types/vislib/public/to_ast_pie.ts +++ b/src/plugins/vis_types/vislib/public/to_ast_pie.ts @@ -11,7 +11,6 @@ import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugi import { PieVisParams } from './pie'; import { vislibPieName, VisTypeVislibPieExpressionFunctionDefinition } from './pie_fn'; -import { getEsaggsFn } from './to_ast_esaggs'; export const toExpressionAst: VisToExpressionAst = async (vis, params) => { const schemas = getVisSchemas(vis, params); @@ -32,7 +31,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, par } ); - const ast = buildExpression([getEsaggsFn(vis), visTypePie]); + const ast = buildExpression([visTypePie]); return ast.toAst(); }; diff --git a/src/plugins/vis_types/xy/public/to_ast.test.ts b/src/plugins/vis_types/xy/public/to_ast.test.ts index ed35017d53edf..e9b597786c33e 100644 --- a/src/plugins/vis_types/xy/public/to_ast.test.ts +++ b/src/plugins/vis_types/xy/public/to_ast.test.ts @@ -23,10 +23,6 @@ jest.mock('@kbn/expressions-plugin/public', () => ({ })), })); -jest.mock('./to_ast_esaggs', () => ({ - getEsaggsFn: jest.fn(), -})); - describe('xy vis toExpressionAst function', () => { let vis: Vis; @@ -42,7 +38,7 @@ describe('xy vis toExpressionAst function', () => { it('should match basic snapshot', () => { toExpressionAst(vis, params); - const [, builtExpression] = (buildExpression as jest.Mock).mock.calls.pop()[0]; + const [builtExpression] = (buildExpression as jest.Mock).mock.calls.pop()[0]; expect(builtExpression).toMatchSnapshot(); }); diff --git a/src/plugins/vis_types/xy/public/to_ast.ts b/src/plugins/vis_types/xy/public/to_ast.ts index bf2ca297f9f38..46ff05f4426a6 100644 --- a/src/plugins/vis_types/xy/public/to_ast.ts +++ b/src/plugins/vis_types/xy/public/to_ast.ts @@ -32,7 +32,6 @@ import { } from './types'; import { visName, VisTypeXyExpressionFunctionDefinition } from './expression_functions/xy_vis_fn'; import { XyVisType } from '../common'; -import { getEsaggsFn } from './to_ast_esaggs'; import { getSeriesParams } from './utils/get_series_params'; import { getSafeId } from './utils/accessors'; @@ -238,7 +237,7 @@ export const toExpressionAst: VisToExpressionAst = async (vis, params splitColumnDimension: dimensions.splitColumn?.map(prepareXYDimension), }); - const ast = buildExpression([getEsaggsFn(vis), visTypeXy]); + const ast = buildExpression([visTypeXy]); return ast.toAst(); }; diff --git a/src/plugins/vis_types/xy/public/to_ast_esaggs.ts b/src/plugins/vis_types/xy/public/to_ast_esaggs.ts deleted file mode 100644 index 1a9079079ebda..0000000000000 --- a/src/plugins/vis_types/xy/public/to_ast_esaggs.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 { Vis } from '@kbn/visualizations-plugin/public'; -import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; -import { - EsaggsExpressionFunctionDefinition, - IndexPatternLoadExpressionFunctionDefinition, -} from '@kbn/data-plugin/public'; - -import { VisParams } from './types'; - -/** - * Get esaggs expressions function - * TODO: replace this with vis.data.aggs!.toExpressionAst(); - * https://github.com/elastic/kibana/issues/61768 - * @param vis - */ -export function getEsaggsFn(vis: Vis) { - return buildExpressionFunction('esaggs', { - index: buildExpression([ - buildExpressionFunction('indexPatternLoad', { - id: vis.data.indexPattern!.id!, - }), - ]), - metricsAtAllLevels: vis.isHierarchical(), - partialRows: false, - aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), - }); -} diff --git a/src/plugins/vis_types/xy/public/vis_types/area.ts b/src/plugins/vis_types/xy/public/vis_types/area.ts index 84a6a65d2753a..0ca07c8067457 100644 --- a/src/plugins/vis_types/xy/public/vis_types/area.ts +++ b/src/plugins/vis_types/xy/public/vis_types/area.ts @@ -35,6 +35,7 @@ export const areaVisTypeDefinition = { description: i18n.translate('visTypeXy.area.areaDescription', { defaultMessage: 'Emphasize the data between an axis and a line.', }), + fetchDatatable: true, toExpressionAst, getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush], updateVisTypeOnParamsChange: getVisTypeFromParams, diff --git a/src/plugins/vis_types/xy/public/vis_types/histogram.ts b/src/plugins/vis_types/xy/public/vis_types/histogram.ts index dd1ee2836b10f..680186eb330f9 100644 --- a/src/plugins/vis_types/xy/public/vis_types/histogram.ts +++ b/src/plugins/vis_types/xy/public/vis_types/histogram.ts @@ -37,6 +37,7 @@ export const histogramVisTypeDefinition = { description: i18n.translate('visTypeXy.histogram.histogramDescription', { defaultMessage: 'Present data in vertical bars on an axis.', }), + fetchDatatable: true, toExpressionAst, getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush], updateVisTypeOnParamsChange: getVisTypeFromParams, diff --git a/src/plugins/vis_types/xy/public/vis_types/horizontal_bar.ts b/src/plugins/vis_types/xy/public/vis_types/horizontal_bar.ts index dda1ead899faf..25fc3142e0e98 100644 --- a/src/plugins/vis_types/xy/public/vis_types/horizontal_bar.ts +++ b/src/plugins/vis_types/xy/public/vis_types/horizontal_bar.ts @@ -37,6 +37,7 @@ export const horizontalBarVisTypeDefinition = { description: i18n.translate('visTypeXy.horizontalBar.horizontalBarDescription', { defaultMessage: 'Present data in horizontal bars on an axis.', }), + fetchDatatable: true, toExpressionAst, getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush], updateVisTypeOnParamsChange: getVisTypeFromParams, diff --git a/src/plugins/vis_types/xy/public/vis_types/line.ts b/src/plugins/vis_types/xy/public/vis_types/line.ts index a4ad14d7f5442..e0c7e081573f3 100644 --- a/src/plugins/vis_types/xy/public/vis_types/line.ts +++ b/src/plugins/vis_types/xy/public/vis_types/line.ts @@ -35,6 +35,7 @@ export const lineVisTypeDefinition = { description: i18n.translate('visTypeXy.line.lineDescription', { defaultMessage: 'Display data as a series of points.', }), + fetchDatatable: true, toExpressionAst, getSupportedTriggers: () => [VIS_EVENT_TO_TRIGGER.filter, VIS_EVENT_TO_TRIGGER.brush], updateVisTypeOnParamsChange: getVisTypeFromParams, diff --git a/src/plugins/visualizations/public/embeddable/to_ast.ts b/src/plugins/visualizations/public/embeddable/to_ast.ts index dc4e931781f7b..80e7217f8d1c1 100644 --- a/src/plugins/visualizations/public/embeddable/to_ast.ts +++ b/src/plugins/visualizations/public/embeddable/to_ast.ts @@ -6,10 +6,9 @@ * Side Public License, v 1. */ -import { ExpressionFunctionKibana, ExpressionFunctionKibanaContext } from '@kbn/data-plugin/public'; -import { buildExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; +import { ExpressionFunctionKibana } from '@kbn/data-plugin/public'; +import { ExpressionAstExpression, buildExpressionFunction } from '@kbn/expressions-plugin/public'; -import { queryToAst, filtersToAst } from '@kbn/data-plugin/common'; import { VisToExpressionAst } from '../types'; /** @@ -19,31 +18,38 @@ import { VisToExpressionAst } from '../types'; * * @internal */ -export const toExpressionAst: VisToExpressionAst = async (vis, params) => { - const { savedSearchId, searchSource } = vis.data; - const query = searchSource?.getField('query'); - let filters = searchSource?.getField('filter'); - if (typeof filters === 'function') { - filters = filters(); +export const toExpressionAst: VisToExpressionAst = async ( + vis, + params +): Promise => { + if (!vis.type.toExpressionAst) { + throw new Error('Visualization type definition should have toExpressionAst function defined'); } - const kibana = buildExpressionFunction('kibana', {}); - const kibanaContext = buildExpressionFunction('kibana_context', { - q: query && queryToAst(query), - filters: filters && filtersToAst(filters), - savedSearchId, - }); - - const ast = buildExpression([kibana, kibanaContext]); - const expression = ast.toAst(); + const searchSource = vis.data.searchSource?.createCopy(); - if (!vis.type.toExpressionAst) { - throw new Error('Visualization type definition should have toExpressionAst function defined'); + if (vis.data.aggs) { + vis.data.aggs.hierarchical = vis.isHierarchical(); + vis.data.aggs.partialRows = + typeof vis.type.hasPartialRows === 'function' + ? vis.type.hasPartialRows(vis) + : vis.type.hasPartialRows; + searchSource?.setField('aggs', vis.data.aggs); } const visExpressionAst = await vis.type.toExpressionAst(vis, params); - // expand the expression chain with a particular visualization expression chain, if it exists - expression.chain.push(...visExpressionAst.chain); + const searchSourceExpressionAst = searchSource?.toExpressionAst({ + asDatatable: vis.type.fetchDatatable, + }); + + const expression = { + ...visExpressionAst, + chain: [ + buildExpressionFunction('kibana', {}).toAst(), + ...(searchSourceExpressionAst?.chain ?? []), + ...visExpressionAst.chain, + ], + }; return expression; }; diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts index 5b1e2afc91dfd..18dcacadcaeab 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -40,10 +40,12 @@ export class BaseVisType { public readonly editorConfig; public hidden; public readonly requiresSearch; + public readonly hasPartialRows; public readonly hierarchicalData; public readonly setup; public readonly getUsedIndexPattern; public readonly inspectorAdapters; + public readonly fetchDatatable: boolean; public readonly toExpressionAst; public readonly getInfoMessage; public readonly updateVisTypeOnParamsChange; @@ -72,9 +74,11 @@ export class BaseVisType { this.hidden = opts.hidden ?? false; this.requiresSearch = opts.requiresSearch ?? false; this.setup = opts.setup; + this.hasPartialRows = opts.hasPartialRows ?? false; this.hierarchicalData = opts.hierarchicalData ?? false; this.getUsedIndexPattern = opts.getUsedIndexPattern; this.inspectorAdapters = opts.inspectorAdapters; + this.fetchDatatable = opts.fetchDatatable ?? false; this.toExpressionAst = opts.toExpressionAst; this.getInfoMessage = opts.getInfoMessage; this.updateVisTypeOnParamsChange = opts.updateVisTypeOnParamsChange; diff --git a/src/plugins/visualizations/public/vis_types/types.ts b/src/plugins/visualizations/public/vis_types/types.ts index 73b3f96ab2ea7..8f6dc309a7145 100644 --- a/src/plugins/visualizations/public/vis_types/types.ts +++ b/src/plugins/visualizations/public/vis_types/types.ts @@ -216,6 +216,10 @@ export interface VisTypeDefinition { * with the selection of a search source - an index pattern or a saved search. */ readonly requiresSearch?: boolean; + /** + * In case when the visualization performs an aggregation, this option will be used to display or hide the rows with partial data. + */ + readonly hasPartialRows?: boolean | ((vis: { params: TVisParams }) => boolean); readonly hierarchicalData?: boolean | ((vis: { params: TVisParams }) => boolean); readonly inspectorAdapters?: Adapters | (() => Adapters); /** @@ -225,6 +229,12 @@ export interface VisTypeDefinition { * of this type. */ readonly getInfoMessage?: (vis: Vis) => React.ReactNode; + + /** + * When truthy, it will perform a search and pass the results to the visualization as a `datatable`. + * @default false + */ + readonly fetchDatatable?: boolean; /** * Should be provided to expand base visualization expression with * custom exprsesion chain, including render expression.