[maps] pass request meta to ITMSSource.getUrlTemplate (#153871)

Fixes https://github.com/elastic/kibana/issues/153804

PR resolves issue by passing `SourceRequestMeta` to
`ITMSSource.getUrlTemplate`, giving `getUrlTemplate` the state needed to
update raster URL when required.

PR also resolves the following tech debt:
* rename `searchFilters` -> `requestMeta` to better reflect contents of
parameter.
* Map API's leak lots of implementation details. This PR took the time
to clean up one instance by moving `isGeoGridPrecisionAware` and
`getGeoGridPrecision` from `ISource` to `IESAggSource`
* moved `geogridPrecision` from `VectorSourceRequestMeta` into
`sourceMeta`.
* Removed `VectorJoinSourceRequestMeta` since its same as
`VectorSourceRequestMeta` now that `VectorSourceRequestMeta` does not
contain `geogridPrecision`

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Nathan Reese 2023-03-29 08:22:31 -06:00 committed by GitHub
parent c4ad98b685
commit 383454e30f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 189 additions and 179 deletions

View file

@ -12,8 +12,8 @@ import { FieldFormatter, MIN_ZOOM, MAX_ZOOM } from '@kbn/maps-plugin/common';
import type {
AbstractSourceDescriptor,
Attribution,
DataFilters,
DataRequestMeta,
SourceRequestMeta,
Timeslice,
} from '@kbn/maps-plugin/common/descriptor_types';
import type {
@ -102,10 +102,6 @@ export class CustomRasterSource implements IRasterSource {
return false;
}
isGeoGridPrecisionAware(): boolean {
return false;
}
isQueryAware(): boolean {
return false;
}
@ -138,10 +134,6 @@ export class CustomRasterSource implements IRasterSource {
return [];
}
getGeoGridPrecision(zoom: number): number {
return 0;
}
isESSource(): boolean {
return false;
}
@ -179,11 +171,11 @@ export class CustomRasterSource implements IRasterSource {
return true;
}
async getUrlTemplate(dataFilters: DataFilters): Promise<string> {
async getUrlTemplate(requestMeta: SourceRequestMeta): Promise<string> {
const defaultUrl =
'https://new.nowcoast.noaa.gov/arcgis/rest/services/nowcoast/radar_meteo_imagery_nexrad_time/MapServer/export?dpi=96&transparent=true&format=png32&time={time}&layers=show%3A3&bbox=-{bbox-epsg-3857}&bboxSR=3857&imageSR=3857&size=256%2C256&f=image';
const { timeslice, timeFilters } = dataFilters;
const { timeslice, timeFilters } = requestMeta;
let timestamp;
if (timeslice) {

View file

@ -37,20 +37,20 @@ export type DataFilters = {
executionContext: KibanaExecutionContext;
};
export type VectorSourceRequestMeta = DataFilters & {
export type SourceRequestMeta = DataFilters & {
applyGlobalQuery: boolean;
applyGlobalTime: boolean;
applyForceRefresh: boolean;
fieldNames: string[];
geogridPrecision?: number;
timesliceMaskField?: string;
sourceQuery?: Query;
sourceMeta: object | null;
isForceRefresh: boolean;
isFeatureEditorOpenForLayer: boolean;
};
export type VectorJoinSourceRequestMeta = Omit<VectorSourceRequestMeta, 'geogridPrecision'>;
export type VectorSourceRequestMeta = SourceRequestMeta & {
fieldNames: string[];
timesliceMaskField?: string;
sourceMeta: object | null;
isFeatureEditorOpenForLayer: boolean;
};
export type VectorStyleRequestMeta = DataFilters & {
dynamicStyleFields: string[];
@ -89,8 +89,8 @@ export type DataRequestMeta = {
// request stop time in milliseconds since epoch
requestStopTime?: number;
} & Partial<
VectorSourceRequestMeta &
VectorJoinSourceRequestMeta &
SourceRequestMeta &
VectorSourceRequestMeta &
VectorStyleRequestMeta &
ESSearchSourceResponseMeta &
ESGeoLineSourceResponseMeta &

View file

@ -22,11 +22,10 @@ export function buildVectorRequestMeta(
return {
...dataFilters,
fieldNames: _.uniq(fieldNames).sort(),
geogridPrecision: source.getGeoGridPrecision(dataFilters.zoom),
sourceQuery: sourceQuery ? sourceQuery : undefined,
applyGlobalQuery: source.getApplyGlobalQuery(),
applyGlobalTime: source.getApplyGlobalTime(),
sourceMeta: source.getSyncMeta(),
sourceMeta: source.getSyncMeta(dataFilters),
applyForceRefresh: source.isESSource() ? source.getApplyForceRefresh() : false,
isForceRefresh,
isFeatureEditorOpenForLayer,

View file

@ -65,11 +65,21 @@ export class RasterTileLayer extends AbstractLayer {
return this._style;
}
async syncData({ startLoading, stopLoading, onLoadError, dataFilters }: DataRequestContext) {
async syncData({
startLoading,
stopLoading,
onLoadError,
dataFilters,
isForceRefresh,
}: DataRequestContext) {
const source = this.getSource();
const nextMeta = {
...dataFilters,
applyGlobalQuery: source.getApplyGlobalQuery(),
applyGlobalTime: source.getApplyGlobalTime(),
applyForceRefresh: source.isESSource() ? source.getApplyForceRefresh() : false,
sourceQuery: this.getQuery() || undefined,
isForceRefresh,
};
const prevDataRequest = this.getSourceDataRequest();
if (prevDataRequest) {
@ -80,7 +90,7 @@ export class RasterTileLayer extends AbstractLayer {
try {
startLoading(SOURCE_DATA_REQUEST_ID, requestToken, nextMeta);
const data: RasterTileSourceData = {
url: await source.getUrlTemplate(dataFilters),
url: await source.getUrlTemplate(nextMeta),
};
stopLoading(SOURCE_DATA_REQUEST_ID, requestToken, data, {});
} catch (error) {

View file

@ -32,7 +32,7 @@ export async function syncBoundsData({
const requestToken = Symbol(`${SOURCE_BOUNDS_DATA_REQUEST_ID}-${layerId}`);
// Do not pass all searchFilters to source.getBoundsForFilters().
// Do not pass all requestMeta to source.getBoundsForFilters().
// For example, do not want to filter bounds request by extent and buffer.
const boundsFilters = {
sourceQuery: sourceQuery ? sourceQuery : undefined,

View file

@ -45,7 +45,6 @@ import {
ESTermSourceDescriptor,
JoinDescriptor,
StyleMetaDescriptor,
VectorJoinSourceRequestMeta,
VectorLayerDescriptor,
VectorSourceRequestMeta,
VectorStyleRequestMeta,
@ -566,14 +565,14 @@ export class AbstractVectorLayer extends AbstractLayer implements IVectorLayer {
const sourceDataId = join.getSourceDataRequestId();
const requestToken = Symbol(`layer-join-refresh:${this.getId()} - ${sourceDataId}`);
const joinRequestMeta: VectorJoinSourceRequestMeta = buildVectorRequestMeta(
const joinRequestMeta = buildVectorRequestMeta(
joinSource,
joinSource.getFieldNames(),
dataFilters,
joinSource.getWhereQuery(),
isForceRefresh,
isFeatureEditorOpenForLayer
) as VectorJoinSourceRequestMeta;
);
const prevDataRequest = this.getDataRequest(sourceDataId);
const canSkipFetch = await canSkipSourceUpdate({

View file

@ -8,7 +8,7 @@
import { i18n } from '@kbn/i18n';
import { GeoJsonProperties } from 'geojson';
import { DataView } from '@kbn/data-plugin/common';
import { IESSource } from '../es_source';
import type { IESAggSource } from './types';
import { AbstractESSource } from '../es_source';
import { esAggFieldsFactory, IESAggField } from '../../fields/agg';
import { AGG_TYPE, COUNT_PROP_LABEL, FIELD_ORIGIN } from '../../../../common/constants';
@ -19,14 +19,6 @@ import { ITooltipProperty } from '../../tooltips/tooltip_property';
export const DEFAULT_METRIC = { type: AGG_TYPE.COUNT };
export interface IESAggSource extends IESSource {
getAggKey(aggType: AGG_TYPE, fieldName: string): string;
getAggLabel(aggType: AGG_TYPE, fieldLabel: string): Promise<string>;
getMetricFields(): IESAggField[];
getMetricFieldForName(fieldName: string): IESAggField | null;
getValueAggsDsl(indexPattern: DataView): { [key: string]: unknown };
}
export abstract class AbstractESAggSource extends AbstractESSource implements IESAggSource {
private readonly _metricFields: IESAggField[];
@ -139,4 +131,12 @@ export abstract class AbstractESAggSource extends AbstractESSource implements IE
return await Promise.all(promises);
}
isGeoGridPrecisionAware(): boolean {
return false;
}
getGeoGridPrecision(zoom: number): number {
return 0;
}
}

View file

@ -5,4 +5,5 @@
* 2.0.
*/
export * from './es_agg_source';
export type { IESAggSource } from './types';
export { AbstractESAggSource, DEFAULT_METRIC } from './es_agg_source';

View file

@ -0,0 +1,21 @@
/*
* 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 { DataView } from '@kbn/data-plugin/common';
import { AGG_TYPE } from '../../../../common/constants';
import type { IESSource } from '../es_source';
import { IESAggField } from '../../fields/agg';
export interface IESAggSource extends IESSource {
getAggKey(aggType: AGG_TYPE, fieldName: string): string;
getAggLabel(aggType: AGG_TYPE, fieldLabel: string): Promise<string>;
getMetricFields(): IESAggField[];
getMetricFieldForName(fieldName: string): IESAggField | null;
getValueAggsDsl(indexPattern: DataView): { [key: string]: unknown };
isGeoGridPrecisionAware(): boolean;
getGeoGridPrecision(zoom: number): number;
}

View file

@ -157,7 +157,6 @@ describe('ESGeoGridSource', () => {
const vectorSourceRequestMeta: VectorSourceRequestMeta = {
isReadOnly: false,
geogridPrecision: 4,
filters: [],
timeFilters: {
from: 'now',
@ -175,7 +174,7 @@ describe('ESGeoGridSource', () => {
language: 'KQL',
},
sourceMeta: null,
zoom: 0,
zoom: 2, // returns 4 precision
isForceRefresh: false,
isFeatureEditorOpenForLayer: false,
executionContext: { name: APP_ID },
@ -290,7 +289,7 @@ describe('ESGeoGridSource', () => {
type: SOURCE_TYPES.ES_GEO_GRID,
requestType: RENDER_AS.HEATMAP,
});
expect(superFineSource.getGeoGridPrecision(10)).toBe(NaN);
expect(superFineSource.getGeoGridPrecision(10)).toBe(0);
});
});

View file

@ -43,6 +43,7 @@ import { LICENSED_FEATURES } from '../../../licensed_features';
import { getHttp } from '../../../kibana_services';
import { GetFeatureActionsArgs, GeoJsonWithMeta, IMvtVectorSource } from '../vector_source';
import {
DataFilters,
ESGeoGridSourceDescriptor,
MapExtent,
SizeDynamicOptions,
@ -56,7 +57,11 @@ import { isMvt } from './is_mvt';
import { VectorStyle } from '../../styles/vector/vector_style';
import { getIconSize } from './get_icon_size';
type ESGeoGridSourceSyncMeta = Pick<ESGeoGridSourceDescriptor, 'requestType' | 'resolution'>;
interface ESGeoGridSourceSyncMeta {
geogridPrecision: number;
requestType: RENDER_AS;
resolution: GRID_RESOLUTION;
}
const MAX_GEOTILE_LEVEL = 29;
@ -135,8 +140,9 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo
);
}
getSyncMeta(): ESGeoGridSourceSyncMeta {
getSyncMeta(dataFilters: DataFilters): ESGeoGridSourceSyncMeta {
return {
geogridPrecision: this.getGeoGridPrecision(dataFilters.zoom),
requestType: this._descriptor.requestType,
resolution: this._descriptor.resolution,
};
@ -189,9 +195,9 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo
}
getGeoGridPrecision(zoom: number): number {
if (this._descriptor.resolution === GRID_RESOLUTION.SUPER_FINE) {
if (this.isMvt()) {
// The target-precision needs to be determined server side.
return NaN;
return 0;
}
const targetGeotileLevel = Math.ceil(zoom) + this._getGeoGridPrecisionResolutionDelta();
@ -441,17 +447,17 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo
async getGeoJsonWithMeta(
layerName: string,
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
registerCancelCallback: (callback: () => void) => void,
isRequestStillActive: () => boolean,
inspectorAdapters: Adapters
): Promise<GeoJsonWithMeta> {
if (!searchFilters.buffer) {
if (!requestMeta.buffer) {
throw new Error('Cannot get GeoJson without searchFilter.buffer');
}
const indexPattern: DataView = await this.getIndexPattern();
const searchSource: ISearchSource = await this.makeSearchSource(searchFilters, 0);
const searchSource: ISearchSource = await this.makeSearchSource(requestMeta, 0);
searchSource.setField('trackTotalHits', false);
let bucketsPerGrid = 1;
@ -469,32 +475,33 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo
// https://github.com/elastic/elasticsearch/issues/60626
const supportsCompositeAgg = !(await this._isGeoShape());
const precision = this.getGeoGridPrecision(requestMeta.zoom);
const features: Feature[] =
supportsCompositeAgg && tooManyBuckets
? await this._compositeAggRequest({
searchSource,
searchSessionId: searchFilters.searchSessionId,
searchSessionId: requestMeta.searchSessionId,
indexPattern,
precision: searchFilters.geogridPrecision || 0,
precision,
layerName,
registerCancelCallback,
bucketsPerGrid,
isRequestStillActive,
bufferedExtent: searchFilters.buffer,
bufferedExtent: requestMeta.buffer,
inspectorAdapters,
executionContext: searchFilters.executionContext,
executionContext: requestMeta.executionContext,
})
: await this._nonCompositeAggRequest({
searchSource,
searchSessionId: searchFilters.searchSessionId,
searchSessionId: requestMeta.searchSessionId,
indexPattern,
precision: searchFilters.geogridPrecision || 0,
precision,
layerName,
registerCancelCallback,
bufferedExtent: searchFilters.buffer,
bufferedExtent: requestMeta.buffer,
tooManyBuckets,
inspectorAdapters,
executionContext: searchFilters.executionContext,
executionContext: requestMeta.executionContext,
});
return {
@ -513,13 +520,13 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo
}
async getTileUrl(
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
refreshToken: string,
hasLabels: boolean,
buffer: number
): Promise<string> {
const dataView = await this.getIndexPattern();
const searchSource = await this.makeSearchSource(searchFilters, 0);
const searchSource = await this.makeSearchSource(requestMeta, 0);
searchSource.setField('aggs', this.getValueAggsDsl(dataView));
const mvtUrlServicePath = getHttp().basePath.prepend(
@ -535,7 +542,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements IMvtVectorSo
params.set('requestBody', encodeMvtResponseBody(searchSource.getSearchRequestBody()));
params.set('renderAs', this._descriptor.requestType);
params.set('token', refreshToken);
const executionContextId = getExecutionContextId(searchFilters.executionContext);
const executionContextId = getExecutionContextId(requestMeta.executionContext);
if (executionContextId) {
params.set('executionContextId', executionContextId);
}

View file

@ -163,7 +163,7 @@ export class ESGeoLineSource extends AbstractESAggSource {
async getGeoJsonWithMeta(
layerName: string,
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
registerCancelCallback: (callback: () => void) => void,
isRequestStillActive: () => boolean,
inspectorAdapters: Adapters
@ -182,7 +182,7 @@ export class ESGeoLineSource extends AbstractESAggSource {
//
// Fetch entities
//
const entitySearchSource = await this.makeSearchSource(searchFilters, 0);
const entitySearchSource = await this.makeSearchSource(requestMeta, 0);
entitySearchSource.setField('trackTotalHits', false);
const splitField = getField(indexPattern, this._descriptor.splitField);
const cardinalityAgg = { precision_threshold: 1 };
@ -217,10 +217,10 @@ export class ESGeoLineSource extends AbstractESAggSource {
requestDescription: i18n.translate('xpack.maps.source.esGeoLine.entityRequestDescription', {
defaultMessage: 'Elasticsearch terms request to fetch entities within map buffer.',
}),
searchSessionId: searchFilters.searchSessionId,
searchSessionId: requestMeta.searchSessionId,
executionContext: mergeExecutionContext(
{ description: 'es_geo_line:entities' },
searchFilters.executionContext
requestMeta.executionContext
),
requestsAdapter: inspectorAdapters.requests,
});
@ -255,7 +255,7 @@ export class ESGeoLineSource extends AbstractESAggSource {
indexPattern
).query;
}
const tracksSearchFilters = { ...searchFilters };
const tracksSearchFilters = { ...requestMeta };
delete tracksSearchFilters.buffer;
const tracksSearchSource = await this.makeSearchSource(tracksSearchFilters, 0);
tracksSearchSource.setField('trackTotalHits', false);
@ -293,10 +293,10 @@ export class ESGeoLineSource extends AbstractESAggSource {
defaultMessage:
'Elasticsearch geo_line request to fetch tracks for entities. Tracks are not filtered by map buffer.',
}),
searchSessionId: searchFilters.searchSessionId,
searchSessionId: requestMeta.searchSessionId,
executionContext: mergeExecutionContext(
{ description: 'es_geo_line:tracks' },
searchFilters.executionContext
requestMeta.executionContext
),
requestsAdapter: inspectorAdapters.requests,
});

View file

@ -29,6 +29,7 @@ import { DataRequestAbortError } from '../../util/data_request';
import { mergeExecutionContext } from '../execution_context_utils';
import { SourceEditorArgs } from '../source';
import {
DataFilters,
ESPewPewSourceDescriptor,
MapExtent,
VectorSourceRequestMeta,
@ -85,6 +86,12 @@ export class ESPewPewSource extends AbstractESAggSource {
return false;
}
getSyncMeta(dataFilters: DataFilters) {
return {
geogridPrecision: this.getGeoGridPrecision(dataFilters.zoom),
};
}
isGeoGridPrecisionAware() {
return true;
}
@ -125,13 +132,13 @@ export class ESPewPewSource extends AbstractESAggSource {
async getGeoJsonWithMeta(
layerName: string,
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
registerCancelCallback: (callback: () => void) => void,
isRequestStillActive: () => boolean,
inspectorAdapters: Adapters
): Promise<GeoJsonWithMeta> {
const indexPattern = await this.getIndexPattern();
const searchSource = await this.makeSearchSource(searchFilters, 0);
const searchSource = await this.makeSearchSource(requestMeta, 0);
searchSource.setField('trackTotalHits', false);
searchSource.setField('aggs', {
destSplit: {
@ -149,7 +156,7 @@ export class ESPewPewSource extends AbstractESAggSource {
sourceGrid: {
geotile_grid: {
field: this._descriptor.sourceGeoField,
precision: searchFilters.geogridPrecision,
precision: this.getGeoGridPrecision(requestMeta.zoom),
size: 500,
},
aggs: {
@ -183,10 +190,10 @@ export class ESPewPewSource extends AbstractESAggSource {
requestDescription: i18n.translate('xpack.maps.source.pewPew.inspectorDescription', {
defaultMessage: 'Source-destination connections request',
}),
searchSessionId: searchFilters.searchSessionId,
searchSessionId: requestMeta.searchSessionId,
executionContext: mergeExecutionContext(
{ description: 'es_pew_pew_source:connections' },
searchFilters.executionContext
requestMeta.executionContext
),
requestsAdapter: inspectorAdapters.requests,
});

View file

@ -88,7 +88,7 @@ describe('ESSearchSource', () => {
});
});
const searchFilters: VectorSourceRequestMeta = {
const requestMeta: VectorSourceRequestMeta = {
isReadOnly: false,
filters: [],
zoom: 0,
@ -116,7 +116,7 @@ describe('ESSearchSource', () => {
geoField: geoFieldName,
indexPatternId: 'ipId',
});
const tileUrl = await esSearchSource.getTileUrl(searchFilters, '1234', false, 5);
const tileUrl = await esSearchSource.getTileUrl(requestMeta, '1234', false, 5);
const urlParts = tileUrl.split('?');
expect(urlParts[0]).toEqual('rootdir/api/maps/mvt/getTile/{z}/{x}/{y}.pbf');
@ -140,7 +140,7 @@ describe('ESSearchSource', () => {
});
const tileUrl = await esSearchSource.getTileUrl(
{
...searchFilters,
...requestMeta,
executionContext: { name: APP_ID, id: 'map1234' },
},
'1234',

View file

@ -271,7 +271,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
async _getTopHits(
layerName: string,
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
registerCancelCallback: (callback: () => void) => void,
inspectorAdapters: Adapters
) {
@ -283,7 +283,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
const indexPattern: DataView = await this.getIndexPattern();
const fieldNames = searchFilters.fieldNames.filter(
const fieldNames = requestMeta.fieldNames.filter(
(fieldName) => fieldName !== this._descriptor.geoField
);
const { docValueFields, sourceOnlyFields, scriptFields } = getDocValueAndSourceFields(
@ -324,7 +324,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
shard_size: DEFAULT_MAX_BUCKETS_LIMIT,
};
const searchSource = await this.makeSearchSource(searchFilters, 0);
const searchSource = await this.makeSearchSource(requestMeta, 0);
searchSource.setField('trackTotalHits', false);
searchSource.setField('aggs', {
totalEntities: {
@ -354,10 +354,10 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
searchSource,
registerCancelCallback,
requestDescription: 'Elasticsearch document top hits request',
searchSessionId: searchFilters.searchSessionId,
searchSessionId: requestMeta.searchSessionId,
executionContext: mergeExecutionContext(
{ description: 'es_search_source:top_hits' },
searchFilters.executionContext
requestMeta.executionContext
),
requestsAdapter: inspectorAdapters.requests,
});
@ -388,17 +388,17 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
};
}
// searchFilters.fieldNames contains geo field and any fields needed for styling features
// requestMeta.fieldNames contains geo field and any fields needed for styling features
// Performs Elasticsearch search request being careful to pull back only required fields to minimize response size
async _getSearchHits(
layerName: string,
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
registerCancelCallback: (callback: () => void) => void,
inspectorAdapters: Adapters
) {
const indexPattern = await this.getIndexPattern();
const fieldNames = searchFilters.fieldNames.filter(
const fieldNames = requestMeta.fieldNames.filter(
(fieldName) => fieldName !== this._descriptor.geoField
);
const { docValueFields, sourceOnlyFields } = getDocValueAndSourceFields(
@ -411,20 +411,20 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
// Use Kibana global time extent instead of timeslice extent when all documents for global time extent can be loaded
// to allow for client-side masking of timeslice
const searchFiltersWithoutTimeslice = { ...searchFilters };
delete searchFiltersWithoutTimeslice.timeslice;
const useSearchFiltersWithoutTimeslice =
searchFilters.timeslice !== undefined &&
(await this.canLoadAllDocuments(searchFiltersWithoutTimeslice, registerCancelCallback));
const requestMetaWithoutTimeslice = { ...requestMeta };
delete requestMetaWithoutTimeslice.timeslice;
const useRequestMetaWithoutTimeslice =
requestMeta.timeslice !== undefined &&
(await this.canLoadAllDocuments(requestMetaWithoutTimeslice, registerCancelCallback));
const maxResultWindow = await this.getMaxResultWindow();
const searchSource = await this.makeSearchSource(
useSearchFiltersWithoutTimeslice ? searchFiltersWithoutTimeslice : searchFilters,
useRequestMetaWithoutTimeslice ? requestMetaWithoutTimeslice : requestMeta,
maxResultWindow,
initialSearchContext
);
searchSource.setField('trackTotalHits', maxResultWindow + 1);
searchSource.setField('fieldsFromSource', searchFilters.fieldNames); // Setting "fields" filters out unused scripted fields
searchSource.setField('fieldsFromSource', requestMeta.fieldNames); // Setting "fields" filters out unused scripted fields
if (sourceOnlyFields.length === 0) {
searchSource.setField('source', false); // do not need anything from _source
} else {
@ -441,24 +441,24 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
searchSource,
registerCancelCallback,
requestDescription: 'Elasticsearch document request',
searchSessionId: searchFilters.searchSessionId,
searchSessionId: requestMeta.searchSessionId,
executionContext: mergeExecutionContext(
{ description: 'es_search_source:doc_search' },
searchFilters.executionContext
requestMeta.executionContext
),
requestsAdapter: inspectorAdapters.requests,
});
const isTimeExtentForTimeslice =
searchFilters.timeslice !== undefined && !useSearchFiltersWithoutTimeslice;
requestMeta.timeslice !== undefined && !useRequestMetaWithoutTimeslice;
return {
hits: resp.hits.hits.reverse(), // Reverse hits so top documents by sort are drawn on top
meta: {
resultsCount: resp.hits.hits.length,
areResultsTrimmed: isTotalHitsGreaterThan(resp.hits.total, resp.hits.hits.length),
timeExtent: isTimeExtentForTimeslice
? searchFilters.timeslice
: timerangeToTimeextent(searchFilters.timeFilters),
? requestMeta.timeslice
: timerangeToTimeextent(requestMeta.timeFilters),
isTimeExtentForTimeslice,
},
};
@ -519,7 +519,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
async getGeoJsonWithMeta(
layerName: string,
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
registerCancelCallback: (callback: () => void) => void,
isRequestStillActive: () => boolean,
inspectorAdapters: Adapters
@ -527,10 +527,10 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
const indexPattern = await this.getIndexPattern();
const { hits, meta } = this._isTopHits()
? await this._getTopHits(layerName, searchFilters, registerCancelCallback, inspectorAdapters)
? await this._getTopHits(layerName, requestMeta, registerCancelCallback, inspectorAdapters)
: await this._getSearchHits(
layerName,
searchFilters,
requestMeta,
registerCancelCallback,
inspectorAdapters
);
@ -546,7 +546,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
});
return properties;
};
const epochMillisFields = searchFilters.fieldNames.filter((fieldName) => {
const epochMillisFields = requestMeta.fieldNames.filter((fieldName) => {
const field = getField(indexPattern, fieldName);
return field.readFromDocValues && field.type === 'date';
});
@ -841,7 +841,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
}
async getTileUrl(
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
refreshToken: string,
hasLabels: boolean,
buffer: number
@ -849,7 +849,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
const dataView = await this.getIndexPattern();
const indexSettings = await loadIndexSettings(dataView.getIndexPattern());
const searchSource = await this.makeSearchSource(searchFilters, indexSettings.maxResultWindow);
const searchSource = await this.makeSearchSource(requestMeta, indexSettings.maxResultWindow);
// searchSource calls dataView.getComputedFields to seed docvalueFields
// dataView.getComputedFields adds each date field in the dataView to docvalueFields to ensure standardized date format across kibana
// we don't need these as they request unneeded fields and bloat responses
@ -864,7 +864,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
// use fields API
searchSource.setField(
'fields',
searchFilters.fieldNames
requestMeta.fieldNames
.filter((fieldName) => {
return fieldName !== this._descriptor.geoField;
})
@ -895,7 +895,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
params.set('buffer', buffer.toString());
params.set('requestBody', encodeMvtResponseBody(requestBody));
params.set('token', refreshToken);
const executionContextId = getExecutionContextId(searchFilters.executionContext);
const executionContextId = getExecutionContextId(requestMeta.executionContext);
if (executionContextId) {
params.set('executionContextId', executionContextId);
}
@ -947,22 +947,22 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource
}
async canLoadAllDocuments(
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
registerCancelCallback: (callback: () => void) => void
) {
const abortController = new AbortController();
registerCancelCallback(() => abortController.abort());
const maxResultWindow = await this.getMaxResultWindow();
const searchSource = await this.makeSearchSource(searchFilters, 0);
const searchSource = await this.makeSearchSource(requestMeta, 0);
searchSource.setField('trackTotalHits', maxResultWindow + 1);
const { rawResponse: resp } = await lastValueFrom(
searchSource.fetch$({
abortSignal: abortController.signal,
sessionId: searchFilters.searchSessionId,
sessionId: requestMeta.searchSessionId,
legacyHitsTotal: false,
executionContext: mergeExecutionContext(
{ description: 'es_search_source:all_doc_counts' },
searchFilters.executionContext
requestMeta.executionContext
),
})
);

View file

@ -15,6 +15,7 @@ import type { KibanaExecutionContext } from '@kbn/core/public';
import { RequestAdapter } from '@kbn/inspector-plugin/common/adapters/request';
import { lastValueFrom } from 'rxjs';
import type { TimeRange } from '@kbn/es-query';
import type { IESAggSource } from '../es_agg_source';
import { AbstractVectorSource, BoundsRequestMeta } from '../vector_source';
import {
getAutocompleteService,
@ -33,7 +34,6 @@ import {
AbstractSourceDescriptor,
DynamicStylePropertyOptions,
MapExtent,
VectorJoinSourceRequestMeta,
VectorSourceRequestMeta,
} from '../../../../common/descriptor_types';
import { IVectorStyle } from '../../styles/vector/vector_style';
@ -207,47 +207,46 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource
}
async makeSearchSource(
searchFilters: VectorSourceRequestMeta | VectorJoinSourceRequestMeta | BoundsRequestMeta,
requestMeta: VectorSourceRequestMeta | BoundsRequestMeta,
limit: number,
initialSearchContext?: object
): Promise<ISearchSource> {
const indexPattern = await this.getIndexPattern();
const globalFilters: Filter[] = searchFilters.applyGlobalQuery ? searchFilters.filters : [];
const globalFilters: Filter[] = requestMeta.applyGlobalQuery ? requestMeta.filters : [];
const allFilters: Filter[] = [...globalFilters];
if (searchFilters.joinKeyFilter) {
allFilters.push(searchFilters.joinKeyFilter);
if (requestMeta.joinKeyFilter) {
allFilters.push(requestMeta.joinKeyFilter);
}
if (this.isFilterByMapBounds() && 'buffer' in searchFilters && searchFilters.buffer) {
if (this.isFilterByMapBounds() && 'buffer' in requestMeta && requestMeta.buffer) {
// buffer can be empty
const geoField = await this._getGeoField();
const buffer: MapExtent =
this.isGeoGridPrecisionAware() &&
'geogridPrecision' in searchFilters &&
typeof searchFilters.geogridPrecision === 'number'
? expandToTileBoundaries(searchFilters.buffer, searchFilters.geogridPrecision)
: searchFilters.buffer;
'isGeoGridPrecisionAware' in this &&
'getGeoGridPrecision' in this &&
(this as IESAggSource).isGeoGridPrecisionAware()
? expandToTileBoundaries(
requestMeta.buffer,
(this as IESAggSource).getGeoGridPrecision(requestMeta.zoom)
)
: requestMeta.buffer;
const extentFilter = createExtentFilter(buffer, [geoField.name]);
allFilters.push(extentFilter);
}
let isFeatureEditorOpenForLayer = false;
if ('isFeatureEditorOpenForLayer' in searchFilters) {
isFeatureEditorOpenForLayer = searchFilters.isFeatureEditorOpenForLayer;
if ('isFeatureEditorOpenForLayer' in requestMeta) {
isFeatureEditorOpenForLayer = requestMeta.isFeatureEditorOpenForLayer;
}
if (
searchFilters.applyGlobalTime &&
(await this.isTimeAware()) &&
!isFeatureEditorOpenForLayer
) {
const timeRange = searchFilters.timeslice
if (requestMeta.applyGlobalTime && (await this.isTimeAware()) && !isFeatureEditorOpenForLayer) {
const timeRange = requestMeta.timeslice
? {
from: new Date(searchFilters.timeslice.from).toISOString(),
to: new Date(searchFilters.timeslice.to).toISOString(),
from: new Date(requestMeta.timeslice.from).toISOString(),
to: new Date(requestMeta.timeslice.to).toISOString(),
mode: 'absolute' as 'absolute',
}
: searchFilters.timeFilters;
: requestMeta.timeFilters;
const filter = getTimeFilter().createFilter(indexPattern, timeRange);
if (filter) {
allFilters.push(filter);
@ -260,23 +259,23 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource
searchSource.setField('index', indexPattern);
searchSource.setField('size', limit);
searchSource.setField('filter', allFilters);
if (searchFilters.applyGlobalQuery && !isFeatureEditorOpenForLayer) {
searchSource.setField('query', searchFilters.query);
if (requestMeta.applyGlobalQuery && !isFeatureEditorOpenForLayer) {
searchSource.setField('query', requestMeta.query);
}
const parents = [];
if (searchFilters.sourceQuery && !isFeatureEditorOpenForLayer) {
if (requestMeta.sourceQuery && !isFeatureEditorOpenForLayer) {
const layerSearchSource = searchService.searchSource.createEmpty();
layerSearchSource.setField('index', indexPattern);
layerSearchSource.setField('query', searchFilters.sourceQuery);
layerSearchSource.setField('query', requestMeta.sourceQuery);
parents.push(layerSearchSource);
}
if (searchFilters.embeddableSearchContext && !isFeatureEditorOpenForLayer) {
if (requestMeta.embeddableSearchContext && !isFeatureEditorOpenForLayer) {
const embeddableSearchSource = searchService.searchSource.createEmpty();
embeddableSearchSource.setField('index', indexPattern);
embeddableSearchSource.setField('query', searchFilters.embeddableSearchContext.query);
embeddableSearchSource.setField('filter', searchFilters.embeddableSearchContext.filters);
embeddableSearchSource.setField('query', requestMeta.embeddableSearchContext.query);
embeddableSearchSource.setField('filter', requestMeta.embeddableSearchContext.filters);
parents.push(embeddableSearchSource);
}

View file

@ -26,7 +26,7 @@ import {
} from '../../../../common/elasticsearch_util';
import {
ESTermSourceDescriptor,
VectorJoinSourceRequestMeta,
VectorSourceRequestMeta,
} from '../../../../common/descriptor_types';
import { PropertiesMap } from '../../../../common/elasticsearch_util';
import { isValidStringConfig } from '../../util/valid_string_config';
@ -122,7 +122,7 @@ export class ESTermSource extends AbstractESAggSource implements ITermJoinSource
}
async getPropertiesMap(
searchFilters: VectorJoinSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
leftSourceName: string,
leftFieldName: string,
registerCancelCallback: (callback: () => void) => void,
@ -133,7 +133,7 @@ export class ESTermSource extends AbstractESAggSource implements ITermJoinSource
}
const indexPattern = await this.getIndexPattern();
const searchSource: ISearchSource = await this.makeSearchSource(searchFilters, 0);
const searchSource: ISearchSource = await this.makeSearchSource(requestMeta, 0);
searchSource.setField('trackTotalHits', false);
const termsField = getField(indexPattern, this._termField.getName());
const termsAgg = {
@ -158,10 +158,10 @@ export class ESTermSource extends AbstractESAggSource implements ITermJoinSource
rightSource: `${indexPattern.getName()}:${this._termField.getName()}`,
},
}),
searchSessionId: searchFilters.searchSessionId,
searchSessionId: requestMeta.searchSessionId,
executionContext: mergeExecutionContext(
{ description: 'es_term_source:terms' },
searchFilters.executionContext
requestMeta.executionContext
),
requestsAdapter: inspectorAdapters.requests,
});

View file

@ -46,7 +46,6 @@ export interface ISource {
getType(): string;
isFieldAware(): boolean;
isFilterByMapBounds(): boolean;
isGeoGridPrecisionAware(): boolean;
isQueryAware(): boolean;
isTimeAware(): Promise<boolean>;
getImmutableProperties(): Promise<ImmutableSourceProperty[]>;
@ -61,7 +60,6 @@ export interface ISource {
getApplyForceRefresh(): boolean;
getIndexPatternIds(): string[];
getQueryableIndexPatternIds(): string[];
getGeoGridPrecision(zoom: number): number;
createFieldFormatter(field: IField): Promise<FieldFormatter | null>;
getValueSuggestions(field: IField, query: string): Promise<string[]>;
getMinZoom(): number;
@ -109,10 +107,6 @@ export class AbstractSource implements ISource {
return false;
}
isGeoGridPrecisionAware(): boolean {
return false;
}
isQueryAware(): boolean {
return false;
}
@ -145,10 +139,6 @@ export class AbstractSource implements ISource {
return [];
}
getGeoGridPrecision(zoom: number): number {
return 0;
}
isESSource(): boolean {
return false;
}

View file

@ -7,10 +7,7 @@
import { TableSource } from './table_source';
import { FIELD_ORIGIN } from '../../../../common/constants';
import {
VectorJoinSourceRequestMeta,
VectorSourceRequestMeta,
} from '../../../../common/descriptor_types';
import { VectorSourceRequestMeta } from '../../../../common/descriptor_types';
describe('TableSource', () => {
describe('getName', () => {
@ -57,7 +54,7 @@ describe('TableSource', () => {
});
const propertiesMap = await tableSource.getPropertiesMap(
{} as unknown as VectorJoinSourceRequestMeta,
{} as unknown as VectorSourceRequestMeta,
'a',
'b',
() => {}

View file

@ -12,7 +12,6 @@ import { FIELD_ORIGIN, SOURCE_TYPES, VECTOR_SHAPE_TYPE } from '../../../../commo
import {
MapExtent,
TableSourceDescriptor,
VectorJoinSourceRequestMeta,
VectorSourceRequestMeta,
} from '../../../../common/descriptor_types';
import { ITermJoinSource } from '../term_join_source';
@ -60,7 +59,7 @@ export class TableSource extends AbstractVectorSource implements ITermJoinSource
}
async getPropertiesMap(
searchFilters: VectorJoinSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
leftSourceName: string,
leftFieldName: string,
registerCancelCallback: (callback: () => void) => void
@ -189,7 +188,7 @@ export class TableSource extends AbstractVectorSource implements ITermJoinSource
// Could be useful to implement, e.g. to preview raw csv data
async getGeoJsonWithMeta(
layerName: string,
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
registerCancelCallback: (callback: () => void) => void,
isRequestStillActive: () => boolean
): Promise<GeoJsonWithMeta> {

View file

@ -10,7 +10,7 @@ import type { KibanaExecutionContext } from '@kbn/core/public';
import { Query } from '@kbn/data-plugin/common/query';
import { Adapters } from '@kbn/inspector-plugin/common/adapters';
import { IField } from '../../fields/field';
import { VectorJoinSourceRequestMeta } from '../../../../common/descriptor_types';
import { VectorSourceRequestMeta } from '../../../../common/descriptor_types';
import { PropertiesMap } from '../../../../common/elasticsearch_util';
import { ITooltipProperty } from '../../tooltips/tooltip_property';
import { ISource } from '../source';
@ -20,7 +20,7 @@ export interface ITermJoinSource extends ISource {
getTermField(): IField;
getWhereQuery(): Query | undefined;
getPropertiesMap(
searchFilters: VectorJoinSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
leftSourceName: string,
leftFieldName: string,
registerCancelCallback: (callback: () => void) => void,

View file

@ -5,8 +5,8 @@
* 2.0.
*/
import { DataFilters } from '../../../../common/descriptor_types';
import { SourceRequestMeta } from '../../../../common/descriptor_types';
import { ISource } from '../source';
export interface ITMSSource extends ISource {
getUrlTemplate(dataFilters: DataFilters): Promise<string>;
getUrlTemplate(requestMeta: SourceRequestMeta): Promise<string>;
}

View file

@ -14,7 +14,7 @@ export interface IMvtVectorSource extends IVectorSource {
* Append refreshToken as a URL parameter to force tile re-fetch on refresh (not required)
*/
getTileUrl(
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
refreshToken: string,
hasLabels: boolean,
buffer: number

View file

@ -28,6 +28,7 @@ import { ITooltipProperty, TooltipProperty } from '../../tooltips/tooltip_proper
import { AbstractSource, ISource } from '../source';
import { IField } from '../../fields/field';
import {
DataFilters,
ESSearchSourceResponseMeta,
MapExtent,
Timeslice,
@ -96,7 +97,7 @@ export interface IVectorSource extends ISource {
): Promise<MapExtent | null>;
getGeoJsonWithMeta(
layerName: string,
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
registerCancelCallback: (callback: () => void) => void,
isRequestStillActive: () => boolean,
inspectorAdapters: Adapters
@ -112,7 +113,7 @@ export interface IVectorSource extends ISource {
* Vector layer avoids unnecessarily re-fetching source data.
* Use getSyncMeta to expose fields that require source data re-fetch when changed.
*/
getSyncMeta(): object | null;
getSyncMeta(dataFilters: DataFilters): object | null;
getFieldNames(): string[];
createField({ fieldName }: { fieldName: string }): IField;
@ -194,7 +195,7 @@ export class AbstractVectorSource extends AbstractSource implements IVectorSourc
async getGeoJsonWithMeta(
layerName: string,
searchFilters: VectorSourceRequestMeta,
requestMeta: VectorSourceRequestMeta,
registerCancelCallback: (callback: () => void) => void,
isRequestStillActive: () => boolean,
inspectorAdapters: Adapters
@ -238,7 +239,7 @@ export class AbstractVectorSource extends AbstractSource implements IVectorSourc
return { tooltipContent: null, areResultsTrimmed: false };
}
getSyncMeta(): object | null {
getSyncMeta(dataFilters: DataFilters): object | null {
return null;
}

View file

@ -72,9 +72,8 @@ export async function canSkipSourceUpdate({
const timeAware = await source.isTimeAware();
const isFieldAware = source.isFieldAware();
const isQueryAware = source.isQueryAware();
const isGeoGridPrecisionAware = source.isGeoGridPrecisionAware();
if (!timeAware && !extentAware && !isFieldAware && !isQueryAware && !isGeoGridPrecisionAware) {
if (!timeAware && !extentAware && !isFieldAware && !isQueryAware) {
return !!prevDataRequest && prevDataRequest.hasDataOrRequestInProgress();
}
@ -128,16 +127,7 @@ export async function canSkipSourceUpdate({
updateDueToSearchSessionId = prevMeta.searchSessionId !== nextRequestMeta.searchSessionId;
}
let updateDueToPrecisionChange = false;
let updateDueToExtentChange = false;
if (isGeoGridPrecisionAware) {
updateDueToPrecisionChange = !_.isEqual(
prevMeta.geogridPrecision,
nextRequestMeta.geogridPrecision
);
}
if (extentAware) {
updateDueToExtentChange = updateDueToExtent(prevMeta, nextRequestMeta);
}
@ -154,7 +144,6 @@ export async function canSkipSourceUpdate({
!updateDueToFilters &&
!updateDueToSourceQuery &&
!updateDueToApplyGlobalQuery &&
!updateDueToPrecisionChange &&
!updateDueToSourceMetaChange &&
!updateDueToSearchSessionId
);