Skip to content

Commit

Permalink
searchsource ad-hoc data views support (#134762)
Browse files Browse the repository at this point in the history
  • Loading branch information
ppisljar authored Jun 28, 2022
1 parent c8520f9 commit 1aba542
Show file tree
Hide file tree
Showing 14 changed files with 85 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ export const createSearchSource = (

// hydrating index pattern
if (searchSourceFields.index) {
fields.index = await indexPatterns.get(searchSourceFields.index);
if (typeof searchSourceFields.index === 'string') {
fields.index = await indexPatterns.get(searchSourceFields.index);
} else {
fields.index = await indexPatterns.create(searchSourceFields.index);
}
}

if (searchSourceFields.parent) {
Expand Down
33 changes: 20 additions & 13 deletions src/plugins/data/common/search/search_source/extract_references.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

import { SavedObjectReference } from '@kbn/core/types';
import { Filter } from '@kbn/es-query';
import { DataViewPersistableStateService } from '@kbn/data-views-plugin/common';
import { SerializedSearchSourceFields } from './types';

import { DATA_VIEW_SAVED_OBJECT_TYPE } from '../..';

export const extractReferences = (
Expand All @@ -18,18 +18,25 @@ export const extractReferences = (
let searchSourceFields: SerializedSearchSourceFields & { indexRefName?: string } = { ...state };
const references: SavedObjectReference[] = [];
if (searchSourceFields.index) {
const indexId = searchSourceFields.index;
const refName = 'kibanaSavedObjectMeta.searchSourceJSON.index';
references.push({
name: refName,
type: DATA_VIEW_SAVED_OBJECT_TYPE,
id: indexId,
});
searchSourceFields = {
...searchSourceFields,
indexRefName: refName,
index: undefined,
};
if (typeof searchSourceFields.index === 'string') {
const indexId = searchSourceFields.index;
const refName = 'kibanaSavedObjectMeta.searchSourceJSON.index';
references.push({
name: refName,
type: DATA_VIEW_SAVED_OBJECT_TYPE,
id: indexId,
});
searchSourceFields = {
...searchSourceFields,
indexRefName: refName,
index: undefined,
};
} else {
const { state: dataViewState, references: dataViewReferences } =
DataViewPersistableStateService.extract(searchSourceFields.index);
searchSourceFields.index = dataViewState;
references.push(...dataViewReferences);
}
}

if (searchSourceFields.filter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import { SavedObjectReference } from '@kbn/core/types';
import { DataViewPersistableStateService } from '@kbn/data-views-plugin/common';
import { SerializedSearchSourceFields } from './types';

export const injectReferences = (
Expand All @@ -26,6 +27,13 @@ export const injectReferences = (
delete searchSourceReturnFields.indexRefName;
}

if (searchSourceFields.index && typeof searchSourceFields.index !== 'string') {
searchSourceFields.index = DataViewPersistableStateService.inject(
searchSourceFields.index,
references
);
}

if (searchSourceReturnFields.filter && Array.isArray(searchSourceReturnFields.filter)) {
searchSourceReturnFields.filter.forEach((filterRow: any) => {
if (!filterRow.meta || !filterRow.meta.indexRefName) {
Expand Down
23 changes: 19 additions & 4 deletions src/plugins/data/common/search/search_source/search_source.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -808,15 +808,31 @@ describe('SearchSource', () => {
});

describe('#serialize', () => {
const indexPattern123 = { id: '123', isPersisted: () => true } as DataView;
test('should reference index patterns', () => {
const indexPattern123 = { id: '123' } as DataView;
searchSource.setField('index', indexPattern123);
const { searchSourceJSON, references } = searchSource.serialize();
expect(references[0].id).toEqual('123');
expect(references[0].type).toEqual('index-pattern');
expect(JSON.parse(searchSourceJSON).indexRefName).toEqual(references[0].name);
});

test('should contain persisted data view by value', () => {
const localDataView = {
id: 'local-123',
isPersisted: () => false,
toSpec: () => ({ id: 'local-123' }),
} as DataView;
searchSource.setField('index', localDataView);
const { searchSourceJSON, references } = searchSource.serialize();
expect(references.length).toEqual(0);
expect(JSON.parse(searchSourceJSON).index).toMatchInlineSnapshot(`
Object {
"id": "local-123",
}
`);
});

test('should add other fields', () => {
searchSource.setField('highlightAll', true);
searchSource.setField('from', 123456);
Expand Down Expand Up @@ -851,7 +867,6 @@ describe('SearchSource', () => {
});

test('should reference index patterns in filters separately from index field', () => {
const indexPattern123 = { id: '123' } as DataView;
searchSource.setField('index', indexPattern123);
const filter = [
{
Expand Down Expand Up @@ -908,8 +923,9 @@ describe('SearchSource', () => {
},
];

const indexPattern123 = { id: '123', isPersisted: () => true } as DataView;

test('should return serialized fields', () => {
const indexPattern123 = { id: '123' } as DataView;
searchSource.setField('index', indexPattern123);
searchSource.setField('filter', () => {
return filter;
Expand Down Expand Up @@ -941,7 +957,6 @@ describe('SearchSource', () => {
});

test('should support nested search sources', () => {
const indexPattern123 = { id: '123' } as DataView;
searchSource.setField('index', indexPattern123);
searchSource.setField('from', 123);
const childSearchSource = searchSource.createChild();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,7 @@ export class SearchSource {
...searchSourceFields,
};
if (index) {
serializedSearchSourceFields.index = index.id;
serializedSearchSourceFields.index = index.isPersisted() ? index.id : index.toSpec();
}
if (sort) {
serializedSearchSourceFields.sort = !Array.isArray(sort) ? [sort] : sort;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
mergeMigrationFunctionMaps,
MigrateFunctionsObject,
} from '@kbn/kibana-utils-plugin/common';
import { DataViewsContract } from '@kbn/data-views-plugin/common';
import { DataViewPersistableStateService, DataViewsContract } from '@kbn/data-views-plugin/common';
import {
createSearchSource,
extractReferences,
Expand All @@ -34,7 +34,20 @@ const getAllMigrations = (): MigrateFunctionsObject => {
});
});

return mergeMigrationFunctionMaps(searchSourceMigrations, filterMigrations);
const dataviewsMigrations = mapValues(
DataViewPersistableStateService.getAllMigrations(),
(migrate) => {
return (state: SerializedSearchSourceFields) => ({
...state,
index: migrate(state.index),
});
}
);

return mergeMigrationFunctionMaps(
mergeMigrationFunctionMaps(searchSourceMigrations, filterMigrations),
dataviewsMigrations
);
};

export class SearchSourceService {
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/data/common/search/search_source/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { SerializableRecord } from '@kbn/utility-types';
import { PersistableStateService } from '@kbn/kibana-utils-plugin/common';
import type { Filter } from '@kbn/es-query';
import type { DataView } from '@kbn/data-views-plugin/common';
import type { DataView, DataViewSpec } from '@kbn/data-views-plugin/common';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { AggConfigSerialized, IAggConfigs } from '../../../public';
import { Query } from '../..';
Expand Down Expand Up @@ -159,7 +159,7 @@ export type SerializedSearchSourceFields = {
/**
* {@link IndexPatternService}
*/
index?: string;
index?: string | DataViewSpec;
searchAfter?: EsQuerySearchAfter;
timeout?: string;
terminate_after?: number;
Expand Down
7 changes: 4 additions & 3 deletions src/plugins/data_views/common/data_views/data_view.stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ export const createStubDataView = ({
deps?: {
fieldFormats?: FieldFormatsStartCommon;
};
}): DataView =>
new DataView({
spec,
}): DataView => {
return new DataView({
spec: { version: '1', ...spec },
metaFields: opts?.metaFields ?? ['_id', '_type', '_source'],
shortDotsEnable: opts?.shortDotsEnable,
fieldFormats: deps?.fieldFormats ?? fieldFormatsMock,
});
};
1 change: 1 addition & 0 deletions src/plugins/data_views/common/data_views/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export * from './_pattern_cache';
export * from './flatten_hit';
export * from './data_view';
export * from './data_views';
export { DataViewPersistableStateService } from './persistable_state';
2 changes: 1 addition & 1 deletion src/plugins/data_views/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export type {
export { DataViewType } from './types';

export type { DataViewsContract, DataViewsServiceDeps } from './data_views';
export { DataViewsService } from './data_views';
export { DataViewsService, DataViewPersistableStateService } from './data_views';
export type {
DataViewListItem,
DataViewsServicePublicMethods,
Expand Down
1 change: 1 addition & 0 deletions src/plugins/discover/public/__mocks__/index_pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export const buildDataViewMock = ({
docvalueFields: [],
getFormatterForField: jest.fn(() => ({ convert: (value: unknown) => value })),
isTimeNanosBased: () => false,
isPersisted: () => true,
} as unknown as DataView;

dataView.isTimeBased = () => !!timeFieldName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ describe('Saved Object', () => {
} as SimpleSavedObject<SavedObjectAttributes>);

const indexPattern = createStubIndexPattern({
spec: { id: 'my-index', title: 'my-index' },
spec: { id: 'my-index', title: 'my-index', version: '1' },
});
savedObject.searchSource!.setField('index', indexPattern);
return savedObject.save(saveOptionsMock).then(() => {
Expand Down Expand Up @@ -411,6 +411,7 @@ describe('Saved Object', () => {
const indexPattern = createStubIndexPattern({
spec: {
id: 'non-existant-index',
version: '1',
},
});

Expand Down
2 changes: 1 addition & 1 deletion src/plugins/visualizations/public/vis.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jest.mock('./services', () => {
getSearch: () => ({
searchSource: {
create: () => {
return new SearchSource({ index: stubIndexPattern });
return new SearchSource({ index: stubIndexPattern.stubDataView });
},
},
}),
Expand Down
6 changes: 5 additions & 1 deletion src/plugins/visualizations/public/vis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,13 @@ export class Vis<TVisParams = VisParams> {
const configStates = this.initializeDefaultsFromSchemas(aggs, this.type.schemas.all || []);

if (!this.data.indexPattern && aggs.length) {
const dataViewId =
typeof state.data.searchSource?.index === 'string'
? state.data.searchSource?.index
: state.data.searchSource?.index?.id;
this.data.indexPattern = new DataView({
spec: {
id: state.data.savedSearchId ?? state.data.searchSource?.index,
id: state.data.savedSearchId ?? dataViewId,
},
fieldFormats: getFieldsFormats(),
});
Expand Down

0 comments on commit 1aba542

Please sign in to comment.