[data views] allow fields param to be passed to field caps request (#147666)

## Summary

Adds new optional `fields` argument to the data view fields for wildcard
api that allows the consumer to request only specific fields as opposed
to always getting all fields.

Co-authored-by: Steph Milovic <stephanie.milovic@elastic.co>
Co-authored-by: Julia Rechkunova <julia.rechkunova@elastic.co>
This commit is contained in:
Matthew Kime 2022-12-20 07:23:40 -06:00 committed by GitHub
parent fe9ea67178
commit 9a5df11ea0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 46 additions and 11 deletions

View file

@ -497,12 +497,8 @@ export class DataViewsService {
getFieldsForWildcard = async (options: GetFieldsOptions): Promise<FieldSpec[]> => {
const metaFields = await this.config.get<string[]>(META_FIELDS);
const { fields } = await this.apiClient.getFieldsForWildcard({
pattern: options.pattern,
...options,
metaFields,
type: options.type,
rollupIndex: options.rollupIndex,
allowNoIndex: options.allowNoIndex,
indexFilter: options.indexFilter,
});
return fields;
};

View file

@ -315,6 +315,7 @@ export interface GetFieldsOptions {
allowNoIndex?: boolean;
indexFilter?: QueryDslQueryContainer;
includeUnmapped?: boolean;
fields?: string[];
}
/**

View file

@ -49,8 +49,16 @@ export class DataViewsApiClient implements IDataViewsApiClient {
* @param options options for fields request
*/
getFieldsForWildcard(options: GetFieldsOptions) {
const { pattern, metaFields, type, rollupIndex, allowNoIndex, indexFilter, includeUnmapped } =
options;
const {
pattern,
metaFields,
type,
rollupIndex,
allowNoIndex,
indexFilter,
includeUnmapped,
fields,
} = options;
return this._request<FieldsForWildcardResponse>(
this._getUrl(['_fields_for_wildcard']),
{
@ -60,6 +68,7 @@ export class DataViewsApiClient implements IDataViewsApiClient {
rollup_index: rollupIndex,
allow_no_index: allowNoIndex,
include_unmapped: includeUnmapped,
fields,
},
indexFilter ? JSON.stringify({ index_filter: indexFilter }) : undefined
).then((response) => {

View file

@ -61,6 +61,7 @@ export class IndexPatternsFetcher {
type?: string;
rollupIndex?: string;
indexFilter?: QueryDslQueryContainer;
fields?: string[];
}): Promise<{ fields: FieldDescriptor[]; indices: string[] }> {
const { pattern, metaFields = [], fieldCapsOptions, type, rollupIndex, indexFilter } = options;
const patternList = Array.isArray(pattern) ? pattern : pattern.split(',');
@ -81,6 +82,7 @@ export class IndexPatternsFetcher {
include_unmapped: fieldCapsOptions?.includeUnmapped,
},
indexFilter,
fields: options.fields || ['*'],
});
if (type === 'rollup' && rollupIndex) {
const rollupFields: FieldDescriptor[] = [];

View file

@ -161,7 +161,7 @@ describe('server/index_patterns/service/lib/es_api', () => {
sinon.assert.calledOnce(fieldCaps);
const passedOpts = fieldCaps.args[0][0];
expect(passedOpts).toHaveProperty('fields', '*');
expect(passedOpts).toHaveProperty('fields', ['*']);
expect(passedOpts).toHaveProperty('ignore_unavailable', true);
expect(passedOpts).toHaveProperty('allow_no_indices', false);
});

View file

@ -44,6 +44,7 @@ interface FieldCapsApiParams {
indices: string[] | string;
fieldCapsOptions?: { allow_no_indices: boolean; include_unmapped?: boolean };
indexFilter?: QueryDslQueryContainer;
fields?: string[];
}
/**
@ -67,12 +68,13 @@ export async function callFieldCapsApi(params: FieldCapsApiParams) {
allow_no_indices: false,
include_unmapped: false,
},
fields = ['*'],
} = params;
try {
return await callCluster.fieldCaps(
{
index: indices,
fields: '*',
fields,
ignore_unavailable: true,
index_filter: indexFilter,
...fieldCapsOptions,

View file

@ -36,6 +36,7 @@ describe('index_patterns/field_capabilities/field_capabilities', () => {
indices: undefined,
fieldCapsOptions: undefined,
indexFilter: undefined,
fields: undefined,
...args,
});

View file

@ -21,6 +21,7 @@ interface FieldCapabilitiesParams {
metaFields: string[];
fieldCapsOptions?: { allow_no_indices: boolean; include_unmapped?: boolean };
indexFilter?: QueryDslQueryContainer;
fields?: string[];
}
/**
@ -34,12 +35,20 @@ interface FieldCapabilitiesParams {
* @return {Promise<{ fields: Array<FieldDescriptor>, indices: Array<string>>}>}
*/
export async function getFieldCapabilities(params: FieldCapabilitiesParams) {
const { callCluster, indices = [], fieldCapsOptions, indexFilter, metaFields = [] } = params;
const {
callCluster,
indices = [],
fieldCapsOptions,
indexFilter,
metaFields = [],
fields,
} = params;
const esFieldCaps = await callFieldCapsApi({
callCluster,
indices,
fieldCapsOptions,
indexFilter,
fields,
});
const fieldsFromFieldCapsByName = keyBy(readFieldCapsResponse(esFieldCaps.body), 'name');

View file

@ -26,7 +26,8 @@ export class IndexPatternsApiServer implements IDataViewsApiClient {
type,
rollupIndex,
allowNoIndex,
indexFilter: indexFilter,
indexFilter,
fields,
}: GetFieldsOptions) {
const indexPatterns = new IndexPatternsFetcher(this.esClient, allowNoIndex);
return await indexPatterns
@ -36,6 +37,7 @@ export class IndexPatternsApiServer implements IDataViewsApiClient {
type,
rollupIndex,
indexFilter,
fields,
})
.catch((err) => {
if (

View file

@ -37,6 +37,7 @@ interface IQuery {
rollup_index?: string;
allow_no_index?: boolean;
include_unmapped?: boolean;
fields?: string[];
}
const validate: RouteValidatorFullConfig<{}, IQuery, IBody> = {
@ -49,6 +50,7 @@ const validate: RouteValidatorFullConfig<{}, IQuery, IBody> = {
rollup_index: schema.maybe(schema.string()),
allow_no_index: schema.maybe(schema.boolean()),
include_unmapped: schema.maybe(schema.boolean()),
fields: schema.maybe(schema.arrayOf(schema.string())),
}),
// not available to get request
body: schema.maybe(schema.object({ index_filter: schema.any() })),
@ -86,6 +88,7 @@ const handler: RequestHandler<{}, IQuery, IBody> = async (context, request, resp
includeUnmapped,
},
indexFilter,
fields: request.query.fields,
});
return response.ok({

View file

@ -90,6 +90,16 @@ export default function ({ getService }) {
.then(ensureFieldsAreSorted);
});
it('returns a single field as requested', async () => {
await supertest
.get('/api/index_patterns/_fields_for_wildcard')
.query({ pattern: 'basic_index', fields: JSON.stringify(['bar']) })
.expect(200, {
fields: [testFields[0]],
indices: ['basic_index'],
});
});
it('always returns a field for all passed meta fields', async () => {
await supertest
.get('/api/index_patterns/_fields_for_wildcard')