Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
12a7764
Initial try to improve SearchSource consumtion in alerting rules
kertal May 11, 2024
2d76169
Remove console.log
kertal May 12, 2024
ccf3289
[KQL] Add util for getting field names from KQL expression
lukasolson May 15, 2024
6252119
Merge branch 'main' into kql/get-field-names
mattkime May 16, 2024
eb3b687
Merge branch 'main' into dataview-lazy-alert-hack
mattkime May 16, 2024
dd0fe49
Fix test mock
lukasolson May 17, 2024
b898c03
Merge branch 'kql/get-field-names' of github.com:lukasolson/kibana in…
lukasolson May 17, 2024
e278819
Merge branch 'main' into kql/get-field-names
lukasolson May 17, 2024
ea2da7f
fields is possibly undefined
mattkime May 17, 2024
085f283
jest tests fixes
mattkime May 17, 2024
12726e2
type fixes
mattkime May 17, 2024
3b44f04
Merge branch 'main' into kql/get-field-names
lukasolson May 17, 2024
33de2e8
Merge branch 'kql/get-field-names' of github.com:lukasolson/kibana in…
lukasolson May 17, 2024
31ab1c9
use data view lazy to load fields, store them in data view
mattkime May 19, 2024
7c3bca9
remove unnecessary changes
mattkime May 19, 2024
bb876f9
Merge branch 'main' into kql/get-field-names
mattkime May 19, 2024
376da3b
jest test fixes
mattkime May 19, 2024
fc90fff
just fake the field formatter dependency
mattkime May 19, 2024
a74727a
format dependency unneeded
mattkime May 19, 2024
0ff11ab
type fix
mattkime May 19, 2024
ebaaed8
Merge branch 'main' into dataview-lazy-alert-hack_mattk
mattkime May 19, 2024
e1db2a8
cleanup
mattkime May 20, 2024
b638477
Merge branch 'dataview-lazy-alert-hack_mattk' of github.com:mattkime/…
mattkime May 20, 2024
48e3563
get metafields and shortdots enabled values
mattkime May 20, 2024
478b45e
Merge branch 'main' into kql/get-field-names
lukasolson May 20, 2024
e7d97cf
Fix reduce without initial value
lukasolson May 20, 2024
e4797cc
Merge branch 'kql/get-field-names' of github.com:lukasolson/kibana in…
lukasolson May 20, 2024
43865f2
Merge branch 'kql/get-field-names' into dataview-lazy-alert-hack_mattk
mattkime May 20, 2024
12e8b33
remove unneeded changes, dupe kql field extraction fn
mattkime May 20, 2024
d7b36eb
Merge branch 'main' into dataview-lazy-alert-hack_mattk
mattkime May 20, 2024
5d3ab0d
Merge branch 'main' into dataview-lazy-alert-hack_mattk
mattkime May 21, 2024
0a87f30
Merge branch 'main' into dataview-lazy-alert-hack_mattk
mattkime May 21, 2024
69826e5
Update src/plugins/data/common/search/search_source/search_source.ts
mattkime May 24, 2024
e3d2d67
Merge branch 'main' into dataview-lazy-alert-hack_mattk
mattkime May 24, 2024
c0a9614
Merge branch 'dataview-lazy-alert-hack_mattk' of github.com:mattkime/…
mattkime May 26, 2024
56b36ae
update snapshot
mattkime May 26, 2024
33e7723
Merge branch 'main' into dataview-lazy-alert-hack_mattk
mattkime May 26, 2024
8096fb1
Update search_source.test.ts
mattkime May 27, 2024
e6f70cf
Merge branch 'main' into dataview-lazy-alert-hack_mattk
mattkime May 30, 2024
72d709c
Merge branch 'main' into dataview-lazy-alert-hack_mattk
mattkime May 30, 2024
f77b0f2
simplify create method code
mattkime May 30, 2024
5499ae0
add unit tests
mattkime May 31, 2024
48f6695
Merge branch 'main' into dataview-lazy-alert-hack_mattk
mistic May 31, 2024
885d3dc
Merge branch 'main' into dataview-lazy-alert-hack_mattk
mattkime Jun 1, 2024
e79c326
remove mergeProps change
mattkime Jun 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/kbn-generate-csv/src/generate_csv.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ describe('CsvGenerator', () => {

const mockSearchSourceService: jest.Mocked<ISearchStartSearchSource> = {
create: jest.fn().mockReturnValue(searchSourceMock),
createLazy: jest.fn().mockReturnValue(searchSourceMock),
createEmpty: jest.fn().mockReturnValue(searchSourceMock),
telemetry: jest.fn(),
inject: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import { createSearchSource as createSearchSourceFactory } from './create_search_source';
import { SearchSourceDependencies } from './search_source';
import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/common';
import type { DataView, DataViewsContract, DataViewLazy } from '@kbn/data-views-plugin/common';
import type { Filter } from '@kbn/es-query';

describe('createSearchSource', () => {
Expand All @@ -24,6 +24,10 @@ describe('createSearchSource', () => {
search: jest.fn(),
onResponse: (req, res) => res,
scriptedFieldsEnabled: true,
dataViews: {
getMetaFields: jest.fn(),
getShortDotsEnable: jest.fn(),
} as unknown as DataViewsContract,
};

indexPatternContractMock = {
Expand Down Expand Up @@ -104,4 +108,63 @@ describe('createSearchSource', () => {
language: 'lucene',
});
});

it('uses DataViews.get', async () => {
const dataViewMock: DataView = {
toSpec: jest.fn().mockReturnValue(Promise.resolve({})),
getSourceFiltering: jest.fn().mockReturnValue({
excludes: [],
}),
} as unknown as DataView;
const get = jest.fn().mockReturnValue(Promise.resolve(dataViewMock));
const getDataViewLazy = jest.fn();
indexPatternContractMock = {
get,
getDataViewLazy,
} as unknown as jest.Mocked<DataViewsContract>;

createSearchSource = createSearchSourceFactory(indexPatternContractMock, dependencies);

await createSearchSource({
index: '123-456',
highlightAll: true,
query: {
query: '',
language: 'kuery',
},
});
expect(get).toHaveBeenCalledWith('123-456');
expect(getDataViewLazy).not.toHaveBeenCalled();
});

it('uses DataViews.getDataViewLazy when flag is passed', async () => {
const dataViewLazyMock: DataViewLazy = {
toSpec: jest.fn().mockReturnValue(Promise.resolve({})),
getSourceFiltering: jest.fn().mockReturnValue({
excludes: [],
}),
} as unknown as DataViewLazy;
const get = jest.fn();
const getDataViewLazy = jest.fn().mockReturnValue(Promise.resolve(dataViewLazyMock));
indexPatternContractMock = {
get,
getDataViewLazy,
} as unknown as jest.Mocked<DataViewsContract>;

createSearchSource = createSearchSourceFactory(indexPatternContractMock, dependencies);

await createSearchSource(
{
index: '123-456',
highlightAll: true,
query: {
query: '',
language: 'kuery',
},
},
true
);
expect(get).not.toHaveBeenCalled();
expect(getDataViewLazy).toHaveBeenCalledWith('123-456');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
* Side Public License, v 1.
*/

import { DataViewsContract } from '@kbn/data-views-plugin/common';
import { DataViewsContract, DataView, DataViewLazy } from '@kbn/data-views-plugin/common';
import { FieldFormatsStartCommon } from '@kbn/field-formats-plugin/common';
import { migrateLegacyQuery } from './migrate_legacy_query';
import { SearchSource, SearchSourceDependencies } from './search_source';
import { SerializedSearchSourceFields } from '../..';
Expand All @@ -33,18 +34,43 @@ export const createSearchSource = (
indexPatterns: DataViewsContract,
searchSourceDependencies: SearchSourceDependencies
) => {
const createFields = async (searchSourceFields: SerializedSearchSourceFields = {}) => {
let dataViewLazy: DataViewLazy | undefined;
const createFields = async (
searchSourceFields: SerializedSearchSourceFields = {},
useDataViewLazy = false
) => {
const { index, parent, ...restOfFields } = searchSourceFields;
const fields: SearchSourceFields = {
...restOfFields,
};

// hydrating index pattern
if (searchSourceFields.index) {
if (typeof searchSourceFields.index === 'string') {
fields.index = await indexPatterns.get(searchSourceFields.index);
if (!useDataViewLazy) {
fields.index =
typeof searchSourceFields.index === 'string'
? await indexPatterns.get(searchSourceFields.index)
: await indexPatterns.create(searchSourceFields.index);
} else {
fields.index = await indexPatterns.create(searchSourceFields.index);
dataViewLazy =
typeof searchSourceFields.index === 'string'
? await indexPatterns.getDataViewLazy(searchSourceFields.index)
: await indexPatterns.createDataViewLazy(searchSourceFields.index);

const [spec, shortDotsEnable, metaFields] = await Promise.all([
dataViewLazy.toSpec(),
searchSourceDependencies.dataViews.getShortDotsEnable(),
searchSourceDependencies.dataViews.getMetaFields(),
]);

const dataView = new DataView({
spec,
// field format functionality is not used within search source
fieldFormats: {} as FieldFormatsStartCommon,
shortDotsEnable,
metaFields,
});
fields.index = dataView;
}
}

Expand All @@ -55,8 +81,11 @@ export const createSearchSource = (
return fields;
};

const createSearchSourceFn = async (searchSourceFields: SerializedSearchSourceFields = {}) => {
const fields = await createFields(searchSourceFields);
const createSearchSourceFn = async (
searchSourceFields: SerializedSearchSourceFields = {},
useDataViewLazy?: boolean
) => {
const fields = await createFields(searchSourceFields, !!useDataViewLazy);
const searchSource = new SearchSource(fields, searchSourceDependencies);

// todo: move to migration script .. create issue
Expand All @@ -65,6 +94,11 @@ export const createSearchSource = (
if (typeof query !== 'undefined') {
searchSource.setField('query', migrateLegacyQuery(query));
}
// using the dataViewLazy check as a type guard
if (useDataViewLazy && dataViewLazy) {
const dataViewFields = await searchSource.loadDataViewFields(dataViewLazy);
fields.index?.fields.replaceAll(Object.values(dataViewFields).map((fld) => fld.toSpec()));
}

return searchSource;
};
Expand Down
7 changes: 7 additions & 0 deletions src/plugins/data/common/search/search_source/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import { of } from 'rxjs';
import type { MockedKeys } from '@kbn/utility-types-jest';
import { uiSettingsServiceMock } from '@kbn/core/public/mocks';
import { DataViewsContract } from '@kbn/data-views-plugin/common';

import { SearchSource, SearchSourceDependencies } from './search_source';
import { ISearchStartSearchSource, ISearchSource, SearchSourceFields } from './types';
Expand Down Expand Up @@ -37,10 +38,12 @@ export const searchSourceInstanceMock: MockedKeys<ISearchSource> = {
toExpressionAst: jest.fn(),
getActiveIndexFilter: jest.fn(),
parseActiveIndexPatternFromQueryString: jest.fn(),
loadDataViewFields: jest.fn(),
};

export const searchSourceCommonMock: jest.Mocked<ISearchStartSearchSource> = {
create: jest.fn().mockReturnValue(searchSourceInstanceMock),
createLazy: jest.fn().mockReturnValue(searchSourceInstanceMock),
createEmpty: jest.fn().mockReturnValue(searchSourceInstanceMock),
telemetry: jest.fn(),
getAllMigrations: jest.fn(),
Expand Down Expand Up @@ -71,4 +74,8 @@ export const createSearchSourceMock = (
),
onResponse: jest.fn().mockImplementation((req, res) => res),
scriptedFieldsEnabled: true,
dataViews: {
getMetaFields: jest.fn(),
getShortDotsEnable: jest.fn(),
} as unknown as DataViewsContract,
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import Rx, { firstValueFrom, lastValueFrom, of, throwError } from 'rxjs';
import type { DataView } from '@kbn/data-views-plugin/common';
import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/common';
import { buildExpression, ExpressionAstExpression } from '@kbn/expressions-plugin/common';
import type { MockedKeys } from '@kbn/utility-types-jest';
import type { ISearchGeneric } from '@kbn/search-types';
Expand Down Expand Up @@ -95,6 +95,10 @@ describe('SearchSource', () => {
search: mockSearchMethod,
onResponse: jest.fn().mockImplementation((_, res) => res),
scriptedFieldsEnabled: true,
dataViews: {
getMetaFields: jest.fn(),
getShortDotsEnable: jest.fn(),
} as unknown as jest.Mocked<DataViewsContract>,
};

searchSource = new SearchSource({}, searchSourceDependencies);
Expand Down
48 changes: 46 additions & 2 deletions src/plugins/data/common/search/search_source/search_source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,15 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import {
buildEsQuery,
Filter,
fromKueryExpression,
isOfQueryType,
isPhraseFilter,
isPhrasesFilter,
getKqlFieldNames,
} 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 { DataView, DataViewLazy, DataViewsContract } from '@kbn/data-views-plugin/common';
import {
ExpressionAstExpression,
buildExpression,
Expand Down Expand Up @@ -134,6 +136,7 @@ export const searchSourceRequiredUiSettings = [
export interface SearchSourceDependencies extends FetchHandlers {
aggs: AggsStart;
search: ISearchGeneric;
dataViews: DataViewsContract;
scriptedFieldsEnabled: boolean;
}

Expand Down Expand Up @@ -712,7 +715,7 @@ export class SearchSource {
}

private readonly getFieldName = (fld: SearchFieldValue): string =>
typeof fld === 'string' ? fld : (fld.field as string);
typeof fld === 'string' ? fld : (fld?.field as string);

private getFieldsWithoutSourceFilters(
index: DataView | undefined,
Expand Down Expand Up @@ -778,6 +781,47 @@ export class SearchSource {
return field;
}

public async loadDataViewFields(dataView: DataViewLazy) {
const request = this.mergeProps(this, { body: {} });
let fields = dataView.timeFieldName ? [dataView.timeFieldName] : [];
const sort = this.getField('sort');
if (sort) {
const sortArr = Array.isArray(sort) ? sort : [sort];
for (const s of sortArr) {
const keys = Object.keys(s);
fields = fields.concat(keys);
}
}
for (const query of request.query) {
if (query.query) {
const nodes = fromKueryExpression(query.query);
const queryFields = getKqlFieldNames(nodes);
fields = fields.concat(queryFields);
}
}
const filters = request.filters;
if (filters) {
const filtersArr = Array.isArray(filters) ? filters : [filters];
for (const f of filtersArr) {
fields = fields.concat(f.meta.key);
}
}
fields = fields.filter((f) => Boolean(f));
Comment thread
mattkime marked this conversation as resolved.
Comment thread
mattkime marked this conversation as resolved.

if (dataView.getSourceFiltering() && dataView.getSourceFiltering().excludes.length) {
// if source filtering is enabled, we need to fetch all the fields
return (await dataView.getFields({ fieldName: ['*'] })).getFieldMapSorted();
Comment on lines +811 to +813
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's another case where we need to load all fields. like @lukasolson mentioned about his code that is used for translating KQL to ES DSL:

// Special case for wildcards where there are no fields or all fields share the same prefix
if (isExistsQuery && (!fields?.length || fields?.length === indexPattern?.fields.length)) {
return { match_all: {} };
}

@lukasolson: I think this is essentially for if you do something like * or :

So if we detect there's just a * field part of the query extracted fields. then we need to load all fields upfront. Also we need to be sure than any wildcard usage in the field names work with the field_caps API, else we also need to load all fields in the general usage of wildcards in fields of KQL.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not following but this clearly needs to be addressed before this PR is merged. @lukasolson can you explain?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems my copy paste did swallow significant details, when users search * or *:* all fields are needed, however might already work, because field caps, when given * should return all fields, right? Anyway it needs to be evaluated, and if would be covered by a test, even better

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kertal are you saying all fields need to loaded via field_caps? If so, how does the field_cap content inform the request?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well if one of the fields in L822 is *, because it was part of the query, field caps will load all fields, wouldn't it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A field might be part of a request without first being loaded by field caps.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how? in this part of the code, we collect all fields that we might need later on to build the ES query, which field might be missed?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we talked in our 1:1 about this, the last missing fields should be all date fields, but these are just used for formatting. to trigger an alert this formatting is not necessary, but the question is, in an alert notification you can add the document triggering the alert, here it might be necessary to apply correct formatting. This is solveable sending 2 field caps requests. 1 for the mandatory fields of query, filter,timestamp ... 1 for all date fields for formatting, combining those into 1 field list on the data view. just 1 request would be better, however 2 requests for a smaller amount of fields should also be a big improvement.

} else if (fields.length) {
return (
await dataView.getFields({
fieldName: fields,
})
).getFieldMapSorted();
}
// no fields needed to be loaded for query
return {};
Comment on lines +815 to +822
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way I see it, the only thing for feature parity to build the same request like before is to get all time fields which are added to to ensure they have the same formatting:

const dateFields = fields.getByType('date');
const dateField = dateFields.find((indexPatternField) => indexPatternField.name === fieldName);
if (!dateField) {
return field;
}
const { esTypes } = dateField;
if (esTypes?.includes('date_nanos')) {
field.format = 'strict_date_optional_time_nanos';
} else if (esTypes?.includes('date')) {
field.format = 'strict_date_optional_time';
}

this code was introduced in #91478 to overcome elastic/elasticsearch#67063
date_nanos needed a format to work correctly back in the days. this was a workaround, that's no longer needed for any functionality. In the alerting case, which is the only current consumer of this changes, this would mean, that once an alert notification attaches documents that triggered a notification, might have a different date formatting.

We could keep this behavior by adding another request, just for date & data_nanos fields and combine this with the result of L821. Downside, it would add another field_caps request, but a small one, so in the end with this PR instead of 1 field_caps request for all fields, we would have 2 small requests, one for the fields in query + filters, one for all date fields. This should be further improved once Elasticsearch supports to specify field formatter by field type elastic/elasticsearch#103705

So the question is should we add fetching of all date/date_nanos fields for this case?

wdyt @elastic/kibana-data-discovery ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, this sounds like an optimization over the current code in this PR. I'd like to capture this idea in and issue along with any other compromises with this implementation. I currently have some optimism this can be resolved through ES support for field formatters by type.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this can definitely be resolved by ES, and it's good to list the compromises. In this case I'm not sure we need to resolve it, since it has no impact on the functionality of an alert, also in case it's configured, the values are returned correctly, it's just the formatting might differ .. if the alert is configured to embed documents in the notification

Copy link
Copy Markdown
Contributor

@lukasolson lukasolson May 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, just played around with this a bit and I'm noticing that alert messages can actually change after this PR...

So imagine I have a document with two fields, date (mapped as a date type) and date_nanos (mapped as a date_nanos type) I have this in my alert message:

{{#context.hits}}
 - {{_source.date}}
 - {{_source.date_nanos}}
 - {{fields.date}}
 - {{fields.date_nanos}}
{{/context.hits}}

Prior to this PR it would actually show the value for each of those:

- 2024-05-30T23:01:34.130Z;
- 2024-05-30T23:01:34.130123456Z;
- 2024-05-30T23:01:34.130Z;
- 2024-05-30T23:01:34.130123456Z;

After this PR it only shows the first three:

- 2024-05-30T22:57:32.409Z;
- 2024-05-30T22:57:32.409123456Z;
- 2024-05-30T22:57:32.409Z;
- ;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As best I understand at this point - we have the choice of either always fetching all date fields OR we need to risk breakage (however small) of fields.* references to date fields. This use case appears incidental but I'll check with @elastic/response-ops

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lukasolson thx for testing, the date_nanos case is interesting, also that _source is available in this context

I expected {{fields.date_nanos}} to have a value available, that's strange. If the data_nanos field would be the data view timefield , there should be a value

like @mattkime mentions we could prevent this by fetching all date/data_nanos fields additionally to the fields we extracted by query + filter.

And then we could revert this when elastic/elasticsearch#103705 is implemented, which allows just to assign one format for all date/date_nanos fields

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update from my end: The way it was implemented before, date fields were just available because of the formatting in the request. No other fields were available, just _source. I therefore would say this should not block this PR, is worth a follow up issue. With this PR more fields are available, via fields. But generally this should be improved, but not in this PR.

}

private flatten() {
const { getConfig } = this.dependencies;
const metaFields = getConfig(UI_SETTINGS.META_FIELDS) ?? [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ describe('SearchSource service', () => {
search: jest.fn(),
onResponse: jest.fn(),
scriptedFieldsEnabled: true,
dataViews: {
getMetaFields: jest.fn(),
getShortDotsEnable: jest.fn(),
} as unknown as DataViewsContract,
};
});

Expand All @@ -32,6 +36,7 @@ describe('SearchSource service', () => {

expect(Object.keys(start)).toEqual([
'create',
'createLazy',
'createEmpty',
'extract',
'inject',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ export class SearchSourceService {
* creates searchsource based on serialized search source fields
*/
create: createSearchSource(indexPatterns, dependencies),
createLazy: (searchSourceFields: SerializedSearchSourceFields = {}) => {
const fn = createSearchSource(indexPatterns, dependencies);
return fn(searchSourceFields, true);
},
/**
* creates an enpty search source
*/
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/data/common/search/search_source/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ export interface ISearchStartSearchSource
* @param fields
*/
create: (fields?: SerializedSearchSourceFields) => Promise<ISearchSource>;

createLazy: (fields?: SerializedSearchSourceFields) => Promise<ISearchSource>;
/**
* creates empty {@link SearchSource}
*/
Expand Down
1 change: 1 addition & 0 deletions src/plugins/data/public/search/search_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
aggs,
getConfig: uiSettings.get.bind(uiSettings),
search,
dataViews: indexPatterns,
onResponse: (request, response, options) => {
if (!options.disableWarningToasts) {
const { rawResponse } = response;
Expand Down
1 change: 1 addition & 0 deletions src/plugins/data/server/search/search_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
getConfig: <T = any>(key: string): T => uiSettingsCache[key],
search: this.asScoped(request).search,
onResponse: (req, res) => res,
dataViews: scopedIndexPatterns,
scriptedFieldsEnabled: true,
};

Expand Down
2 changes: 1 addition & 1 deletion src/plugins/data_views/common/data_views/data_view_lazy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class DataViewLazy extends AbstractDataView {

return {
getFieldMap: () => fieldMap,
getFieldMapSorted: () => {
getFieldMapSorted: (): Record<string, DataViewField> => {
if (!hasBeenSorted) {
fieldMapSorted = chain(fieldMap).toPairs().sortBy(0).fromPairs().value();
hasBeenSorted = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ describe('getSavedSearch', () => {
"getSearchRequestBody": [MockFunction],
"getSerializedFields": [MockFunction],
"history": Array [],
"loadDataViewFields": [MockFunction],
"onRequestStart": [MockFunction],
"parseActiveIndexPatternFromQueryString": [MockFunction],
"removeField": [MockFunction],
Expand Down Expand Up @@ -231,6 +232,7 @@ describe('getSavedSearch', () => {
"getSearchRequestBody": [MockFunction],
"getSerializedFields": [MockFunction],
"history": Array [],
"loadDataViewFields": [MockFunction],
"onRequestStart": [MockFunction],
"parseActiveIndexPatternFromQueryString": [MockFunction],
"removeField": [MockFunction],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ describe('saved_searches_utils', () => {
"aggs": Object {
"createAggConfigs": [MockFunction],
},
"dataViews": Object {
"getMetaFields": [MockFunction],
"getShortDotsEnable": [MockFunction],
},
"getConfig": [MockFunction],
"onResponse": [MockFunction],
"scriptedFieldsEnabled": true,
Expand Down
Loading