mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Maps] Support query-time runtime fields (#95701)
This commit is contained in:
parent
88847b9845
commit
324c6c05a4
8 changed files with 116 additions and 52 deletions
|
@ -61,54 +61,12 @@ import { DataRequest } from '../../util/data_request';
|
|||
import { SortDirection, SortDirectionNumeric } from '../../../../../../../src/plugins/data/common';
|
||||
import { isValidStringConfig } from '../../util/valid_string_config';
|
||||
import { TopHitsUpdateSourceEditor } from './top_hits';
|
||||
import { getDocValueAndSourceFields, ScriptField } from './get_docvalue_source_fields';
|
||||
|
||||
export const sourceTitle = i18n.translate('xpack.maps.source.esSearchTitle', {
|
||||
defaultMessage: 'Documents',
|
||||
});
|
||||
|
||||
export interface ScriptField {
|
||||
source: string;
|
||||
lang: string;
|
||||
}
|
||||
|
||||
function getDocValueAndSourceFields(
|
||||
indexPattern: IndexPattern,
|
||||
fieldNames: string[],
|
||||
dateFormat: string
|
||||
): {
|
||||
docValueFields: Array<string | { format: string; field: string }>;
|
||||
sourceOnlyFields: string[];
|
||||
scriptFields: Record<string, { script: ScriptField }>;
|
||||
} {
|
||||
const docValueFields: Array<string | { format: string; field: string }> = [];
|
||||
const sourceOnlyFields: string[] = [];
|
||||
const scriptFields: Record<string, { script: ScriptField }> = {};
|
||||
fieldNames.forEach((fieldName) => {
|
||||
const field = getField(indexPattern, fieldName);
|
||||
if (field.scripted) {
|
||||
scriptFields[field.name] = {
|
||||
script: {
|
||||
source: field.script || '',
|
||||
lang: field.lang || '',
|
||||
},
|
||||
};
|
||||
} else if (field.readFromDocValues) {
|
||||
const docValueField =
|
||||
field.type === 'date'
|
||||
? {
|
||||
field: fieldName,
|
||||
format: dateFormat,
|
||||
}
|
||||
: fieldName;
|
||||
docValueFields.push(docValueField);
|
||||
} else {
|
||||
sourceOnlyFields.push(fieldName);
|
||||
}
|
||||
});
|
||||
|
||||
return { docValueFields, sourceOnlyFields, scriptFields };
|
||||
}
|
||||
|
||||
export class ESSearchSource extends AbstractESSource implements ITiledSingleLayerVectorSource {
|
||||
readonly _descriptor: ESSearchSourceDescriptor;
|
||||
protected readonly _tooltipFields: ESDocField[];
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { getDocValueAndSourceFields } from './get_docvalue_source_fields';
|
||||
import { IndexPattern } from '../../../../../../../src/plugins/data/common/index_patterns/index_patterns';
|
||||
import { IFieldType } from '../../../../../../../src/plugins/data/common/index_patterns/fields';
|
||||
|
||||
function createMockIndexPattern(fields: IFieldType[]): IndexPattern {
|
||||
const indexPattern = {
|
||||
get fields() {
|
||||
return {
|
||||
getByName(fieldname: string) {
|
||||
return fields.find((f) => f.name === fieldname);
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
return (indexPattern as unknown) as IndexPattern;
|
||||
}
|
||||
|
||||
describe('getDocValueAndSourceFields', () => {
|
||||
it('should add runtime fields to docvalue fields', () => {
|
||||
const { docValueFields } = getDocValueAndSourceFields(
|
||||
createMockIndexPattern([
|
||||
{
|
||||
name: 'foobar',
|
||||
// @ts-expect-error runtimeField not added yet to IFieldType. API tbd
|
||||
runtimeField: {},
|
||||
},
|
||||
]),
|
||||
['foobar'],
|
||||
'epoch_millis'
|
||||
);
|
||||
|
||||
expect(docValueFields).toEqual(['foobar']);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { IndexPattern } from '../../../../../../../src/plugins/data/common/index_patterns/index_patterns';
|
||||
import { getField } from '../../../../common/elasticsearch_util';
|
||||
|
||||
export interface ScriptField {
|
||||
source: string;
|
||||
lang: string;
|
||||
}
|
||||
|
||||
export function getDocValueAndSourceFields(
|
||||
indexPattern: IndexPattern,
|
||||
fieldNames: string[],
|
||||
dateFormat: string
|
||||
): {
|
||||
docValueFields: Array<string | { format: string; field: string }>;
|
||||
sourceOnlyFields: string[];
|
||||
scriptFields: Record<string, { script: ScriptField }>;
|
||||
} {
|
||||
const docValueFields: Array<string | { format: string; field: string }> = [];
|
||||
const sourceOnlyFields: string[] = [];
|
||||
const scriptFields: Record<string, { script: ScriptField }> = {};
|
||||
fieldNames.forEach((fieldName) => {
|
||||
const field = getField(indexPattern, fieldName);
|
||||
if (field.scripted) {
|
||||
scriptFields[field.name] = {
|
||||
script: {
|
||||
source: field.script || '',
|
||||
lang: field.lang || '',
|
||||
},
|
||||
};
|
||||
}
|
||||
// @ts-expect-error runtimeField has not been added to public API yet. exact shape of type TBD.
|
||||
else if (field.readFromDocValues || field.runtimeField) {
|
||||
const docValueField =
|
||||
field.type === 'date'
|
||||
? {
|
||||
field: fieldName,
|
||||
format: dateFormat,
|
||||
}
|
||||
: fieldName;
|
||||
docValueFields.push(docValueField);
|
||||
} else {
|
||||
sourceOnlyFields.push(fieldName);
|
||||
}
|
||||
});
|
||||
|
||||
return { docValueFields, sourceOnlyFields, scriptFields };
|
||||
}
|
|
@ -69,7 +69,9 @@ export default function ({ getPageObjects, getService }) {
|
|||
await dashboardPanelActions.openInspectorByTitle('join example');
|
||||
await retry.try(async () => {
|
||||
const joinExampleRequestNames = await inspector.getRequestNames();
|
||||
expect(joinExampleRequestNames).to.equal('geo_shapes*,meta_for_geo_shapes*.shape_name');
|
||||
expect(joinExampleRequestNames).to.equal(
|
||||
'geo_shapes*,meta_for_geo_shapes*.runtime_shape_name'
|
||||
);
|
||||
});
|
||||
await inspector.close();
|
||||
|
||||
|
@ -90,7 +92,7 @@ export default function ({ getPageObjects, getService }) {
|
|||
await filterBar.selectIndexPattern('logstash-*');
|
||||
await filterBar.addFilter('machine.os', 'is', 'win 8');
|
||||
await filterBar.selectIndexPattern('meta_for_geo_shapes*');
|
||||
await filterBar.addFilter('shape_name', 'is', 'alpha');
|
||||
await filterBar.addFilter('shape_name', 'is', 'alpha'); // runtime fields do not have autocomplete
|
||||
|
||||
const gridResponse = await PageObjects.maps.getResponseFromDashboardPanel(
|
||||
'geo grid vector grid example'
|
||||
|
@ -99,7 +101,7 @@ export default function ({ getPageObjects, getService }) {
|
|||
|
||||
const joinResponse = await PageObjects.maps.getResponseFromDashboardPanel(
|
||||
'join example',
|
||||
'meta_for_geo_shapes*.shape_name'
|
||||
'meta_for_geo_shapes*.runtime_shape_name'
|
||||
);
|
||||
expect(joinResponse.aggregations.join.buckets.length).to.equal(1);
|
||||
});
|
||||
|
|
|
@ -59,7 +59,7 @@ export default function ({ getPageObjects, getService }) {
|
|||
// const hasSourceFilter = await filterBar.hasFilter('name', 'charlie');
|
||||
// expect(hasSourceFilter).to.be(true);
|
||||
|
||||
const hasJoinFilter = await filterBar.hasFilter('shape_name', 'charlie');
|
||||
const hasJoinFilter = await filterBar.hasFilter('runtime_shape_name', 'charlie');
|
||||
expect(hasJoinFilter).to.be(true);
|
||||
});
|
||||
});
|
||||
|
@ -78,7 +78,7 @@ export default function ({ getPageObjects, getService }) {
|
|||
const panelCount = await PageObjects.dashboard.getPanelCount();
|
||||
expect(panelCount).to.equal(2);
|
||||
|
||||
const hasJoinFilter = await filterBar.hasFilter('shape_name', 'charlie');
|
||||
const hasJoinFilter = await filterBar.hasFilter('runtime_shape_name', 'charlie');
|
||||
expect(hasJoinFilter).to.be(true);
|
||||
});
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ export default function ({ getPageObjects, getService }) {
|
|||
|
||||
it('should re-fetch join with refresh timer', async () => {
|
||||
async function getRequestTimestamp() {
|
||||
await PageObjects.maps.openInspectorRequest('meta_for_geo_shapes*.shape_name');
|
||||
await PageObjects.maps.openInspectorRequest('meta_for_geo_shapes*.runtime_shape_name');
|
||||
const requestStats = await inspector.getTableData();
|
||||
const requestTimestamp = PageObjects.maps.getInspectorStatRowHit(
|
||||
requestStats,
|
||||
|
@ -121,7 +121,9 @@ export default function ({ getPageObjects, getService }) {
|
|||
});
|
||||
|
||||
it('should not apply query to source and apply query to join', async () => {
|
||||
const joinResponse = await PageObjects.maps.getResponse('meta_for_geo_shapes*.shape_name');
|
||||
const joinResponse = await PageObjects.maps.getResponse(
|
||||
'meta_for_geo_shapes*.runtime_shape_name'
|
||||
);
|
||||
expect(joinResponse.aggregations.join.buckets.length).to.equal(2);
|
||||
});
|
||||
});
|
||||
|
@ -136,7 +138,9 @@ export default function ({ getPageObjects, getService }) {
|
|||
});
|
||||
|
||||
it('should apply query to join request', async () => {
|
||||
const joinResponse = await PageObjects.maps.getResponse('meta_for_geo_shapes*.shape_name');
|
||||
const joinResponse = await PageObjects.maps.getResponse(
|
||||
'meta_for_geo_shapes*.runtime_shape_name'
|
||||
);
|
||||
expect(joinResponse.aggregations.join.buckets.length).to.equal(1);
|
||||
});
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
"index": ".kibana",
|
||||
"source": {
|
||||
"index-pattern": {
|
||||
"runtimeFieldMap" : "{\"runtime_shape_name\":{\"type\":\"keyword\",\"script\":{\"source\":\"emit(doc['shape_name'].value)\"}}}",
|
||||
"fields" : "[]",
|
||||
"title": "meta_for_geo_shapes*"
|
||||
},
|
||||
|
@ -498,7 +499,7 @@
|
|||
"type": "envelope"
|
||||
},
|
||||
"description": "",
|
||||
"layerListJSON" : "[{\"id\":\"n1t6f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"62eca1fc-fe42-11e8-8eb2-f2801f1b9fd1\",\"type\":\"ES_SEARCH\",\"geoField\":\"geometry\",\"limit\":2048,\"filterByMapBounds\":false,\"showTooltip\":true,\"tooltipProperties\":[\"name\"],\"applyGlobalQuery\":false,\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3},\"field\":{\"label\":\"max(prop1) group by meta_for_geo_shapes*.shape_name\",\"name\":\"__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.shape_name\",\"origin\":\"join\"},\"color\":\"Blues\"}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\",\"joins\":[{\"leftField\":\"name\",\"right\":{\"id\":\"855ccb86-fe42-11e8-8eb2-f2801f1b9fd1\",\"indexPatternTitle\":\"meta_for_geo_shapes*\",\"term\":\"shape_name\",\"metrics\":[{\"type\":\"max\",\"field\":\"prop1\"}],\"applyGlobalQuery\":true,\"indexPatternRefName\":\"layer_1_join_0_index_pattern\"}}]}]",
|
||||
"layerListJSON" : "[{\"id\":\"n1t6f\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"62eca1fc-fe42-11e8-8eb2-f2801f1b9fd1\",\"type\":\"ES_SEARCH\",\"geoField\":\"geometry\",\"limit\":2048,\"filterByMapBounds\":false,\"showTooltip\":true,\"tooltipProperties\":[\"name\"],\"applyGlobalQuery\":false,\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"fieldMetaOptions\":{\"isEnabled\":false,\"sigma\":3},\"field\":{\"label\":\"max(prop1) group by meta_for_geo_shapes*.runtime_shape_name\",\"name\":\"__kbnjoin__max_of_prop1_groupby_meta_for_geo_shapes*.runtime_shape_name\",\"origin\":\"join\"},\"color\":\"Blues\"}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}}},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\",\"joins\":[{\"leftField\":\"name\",\"right\":{\"id\":\"855ccb86-fe42-11e8-8eb2-f2801f1b9fd1\",\"indexPatternTitle\":\"meta_for_geo_shapes*\",\"term\":\"runtime_shape_name\",\"metrics\":[{\"type\":\"max\",\"field\":\"prop1\"}],\"applyGlobalQuery\":true,\"indexPatternRefName\":\"layer_1_join_0_index_pattern\"}}]}]",
|
||||
"mapStateJSON": "{\"zoom\":3.02,\"center\":{\"lon\":77.33426,\"lat\":-0.04647},\"timeFilters\":{\"from\":\"now-17m\",\"to\":\"now\",\"mode\":\"quick\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}",
|
||||
"title": "join example",
|
||||
"uiStateJSON": "{\"isLayerTOCOpen\":true,\"openTOCDetails\":[\"n1t6f\"]}"
|
||||
|
|
|
@ -136,6 +136,9 @@
|
|||
"fieldFormatMap": {
|
||||
"type": "text"
|
||||
},
|
||||
"runtimeFieldMap": {
|
||||
"type": "text"
|
||||
},
|
||||
"fields": {
|
||||
"type": "text"
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue