Skip to content

Commit 0c77354

Browse files
authored
[Maps] gather field formatters in data request (#53311) (#53492)
* [Maps] gather field formatters in data request so they can be used sync in vector_style * review feedback * hasMatchingMetricField * review feedback * fix typo in function name
1 parent 44f86ce commit 0c77354

File tree

6 files changed

+156
-22
lines changed

6 files changed

+156
-22
lines changed

x-pack/legacy/plugins/maps/common/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ export const FIELD_ORIGIN = {
5959
export const SOURCE_DATA_ID_ORIGIN = 'source';
6060
export const META_ID_ORIGIN_SUFFIX = 'meta';
6161
export const SOURCE_META_ID_ORIGIN = `${SOURCE_DATA_ID_ORIGIN}_${META_ID_ORIGIN_SUFFIX}`;
62+
export const FORMATTERS_ID_ORIGIN_SUFFIX = 'formatters';
63+
export const SOURCE_FORMATTERS_ID_ORIGIN = `${SOURCE_DATA_ID_ORIGIN}_${FORMATTERS_ID_ORIGIN_SUFFIX}`;
6264

6365
export const GEOJSON_FILE = 'GEOJSON_FILE';
6466

x-pack/legacy/plugins/maps/public/layers/joins/inner_join.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import { ESTermSource } from '../sources/es_term_source';
88
import { getComputedFieldNamePrefix } from '../styles/vector/style_util';
9-
import { META_ID_ORIGIN_SUFFIX } from '../../../common/constants';
9+
import { META_ID_ORIGIN_SUFFIX, FORMATTERS_ID_ORIGIN_SUFFIX } from '../../../common/constants';
1010

1111
export class InnerJoin {
1212
constructor(joinDescriptor, leftSource) {
@@ -45,6 +45,10 @@ export class InnerJoin {
4545
return `${this.getSourceDataRequestId()}_${META_ID_ORIGIN_SUFFIX}`;
4646
}
4747

48+
getSourceFormattersDataRequestId() {
49+
return `${this.getSourceDataRequestId()}_${FORMATTERS_ID_ORIGIN_SUFFIX}`;
50+
}
51+
4852
getLeftField() {
4953
return this._leftField;
5054
}

x-pack/legacy/plugins/maps/public/layers/sources/es_agg_source.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ export class AbstractESAggSource extends AbstractESSource {
8282
});
8383
}
8484

85+
hasMatchingMetricField(fieldName) {
86+
const matchingField = this.getMetricFieldForName(fieldName);
87+
return !!matchingField;
88+
}
89+
8590
getMetricFieldForName(fieldName) {
8691
return this.getMetricFields().find(metricField => {
8792
return metricField.getName() === fieldName;

x-pack/legacy/plugins/maps/public/layers/styles/vector/vector_style.js

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
FIELD_ORIGIN,
2020
STYLE_TYPE,
2121
SOURCE_META_ID_ORIGIN,
22+
SOURCE_FORMATTERS_ID_ORIGIN,
2223
LAYER_STYLE_TYPE,
2324
} from '../../../../common/constants';
2425
import { VectorIcon } from './components/legend/vector_icon';
@@ -294,14 +295,17 @@ export class VectorStyle extends AbstractStyle {
294295
return this._isOnlySingleFeatureType(VECTOR_SHAPE_TYPES.POLYGON);
295296
};
296297

297-
_getFieldMeta = fieldName => {
298-
const fieldMetaFromLocalFeatures = _.get(this._descriptor, ['__styleMeta', fieldName]);
299-
298+
_getDynamicPropertyByFieldName(fieldName) {
300299
const dynamicProps = this.getDynamicPropertiesArray();
301-
const dynamicProp = dynamicProps.find(dynamicProp => {
300+
return dynamicProps.find(dynamicProp => {
302301
return fieldName === dynamicProp.getField().getName();
303302
});
303+
}
304304

305+
_getFieldMeta = fieldName => {
306+
const fieldMetaFromLocalFeatures = _.get(this._descriptor, ['__styleMeta', fieldName]);
307+
308+
const dynamicProp = this._getDynamicPropertyByFieldName(fieldName);
305309
if (!dynamicProp || !dynamicProp.isFieldMetaEnabled()) {
306310
return fieldMetaFromLocalFeatures;
307311
}
@@ -311,8 +315,7 @@ export class VectorStyle extends AbstractStyle {
311315
dataRequestId = SOURCE_META_ID_ORIGIN;
312316
} else {
313317
const join = this._layer.getValidJoins().find(join => {
314-
const matchingField = join.getRightJoinSource().getMetricFieldForName(fieldName);
315-
return !!matchingField;
318+
return join.getRightJoinSource().hasMatchingMetricField(fieldName);
316319
});
317320
if (join) {
318321
dataRequestId = join.getSourceMetaDataRequestId();
@@ -323,7 +326,7 @@ export class VectorStyle extends AbstractStyle {
323326
return fieldMetaFromLocalFeatures;
324327
}
325328

326-
const styleMetaDataRequest = this._layer._findDataRequestForSource(dataRequestId);
329+
const styleMetaDataRequest = this._layer._findDataRequestById(dataRequestId);
327330
if (!styleMetaDataRequest || !styleMetaDataRequest.hasData()) {
328331
return fieldMetaFromLocalFeatures;
329332
}
@@ -334,6 +337,37 @@ export class VectorStyle extends AbstractStyle {
334337
return fieldMeta ? fieldMeta : fieldMetaFromLocalFeatures;
335338
};
336339

340+
_getFieldFormatter(fieldName) {
341+
const dynamicProp = this._getDynamicPropertyByFieldName(fieldName);
342+
if (!dynamicProp) {
343+
return null;
344+
}
345+
346+
let dataRequestId;
347+
if (dynamicProp.getFieldOrigin() === FIELD_ORIGIN.SOURCE) {
348+
dataRequestId = SOURCE_FORMATTERS_ID_ORIGIN;
349+
} else {
350+
const join = this._layer.getValidJoins().find(join => {
351+
return join.getRightJoinSource().hasMatchingMetricField(fieldName);
352+
});
353+
if (join) {
354+
dataRequestId = join.getSourceFormattersDataRequestId();
355+
}
356+
}
357+
358+
if (!dataRequestId) {
359+
return null;
360+
}
361+
362+
const formattersDataRequest = this._layer._findDataRequestById(dataRequestId);
363+
if (!formattersDataRequest || !formattersDataRequest.hasData()) {
364+
return null;
365+
}
366+
367+
const formatters = formattersDataRequest.getData();
368+
return formatters[fieldName];
369+
}
370+
337371
_getStyleMeta = () => {
338372
return _.get(this._descriptor, '__styleMeta', {});
339373
};
@@ -382,7 +416,7 @@ export class VectorStyle extends AbstractStyle {
382416
const promises = styles.map(async style => {
383417
return {
384418
label: await style.getField().getLabel(),
385-
fieldFormatter: await this._source.getFieldFormatter(style.getField().getName()),
419+
fieldFormatter: this._getFieldFormatter(style.getField().getName()),
386420
meta: this._getFieldMeta(style.getField().getName()),
387421
style,
388422
};
@@ -539,14 +573,10 @@ export class VectorStyle extends AbstractStyle {
539573
fieldName: fieldDescriptor.name,
540574
});
541575
} else if (fieldDescriptor.origin === FIELD_ORIGIN.JOIN) {
542-
let matchingField = null;
543-
const joins = this._layer.getValidJoins();
544-
joins.find(join => {
545-
const aggSource = join.getRightJoinSource();
546-
matchingField = aggSource.getMetricFieldForName(fieldDescriptor.name);
547-
return !!matchingField;
576+
const join = this._layer.getValidJoins().find(join => {
577+
return join.getRightJoinSource().hasMatchingMetricField(fieldDescriptor.name);
548578
});
549-
return matchingField;
579+
return join ? join.getRightJoinSource().getMetricFieldForName(fieldDescriptor.name) : null;
550580
} else {
551581
throw new Error(`Unknown origin-type ${fieldDescriptor.origin}`);
552582
}

x-pack/legacy/plugins/maps/public/layers/util/can_skip_fetch.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,15 @@ export function canSkipStyleMetaUpdate({ prevDataRequest, nextMeta }) {
158158
!updateDueToFields && !updateDueToSourceQuery && !updateDueToIsTimeAware && !updateDueToTime
159159
);
160160
}
161+
162+
export function canSkipFormattersUpdate({ prevDataRequest, nextMeta }) {
163+
if (!prevDataRequest) {
164+
return false;
165+
}
166+
const prevMeta = prevDataRequest.getMeta();
167+
if (!prevMeta) {
168+
return false;
169+
}
170+
171+
return !_.isEqual(prevMeta.fieldNames, nextMeta.fieldNames);
172+
}

x-pack/legacy/plugins/maps/public/layers/vector_layer.js

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
FEATURE_ID_PROPERTY_NAME,
1414
SOURCE_DATA_ID_ORIGIN,
1515
SOURCE_META_ID_ORIGIN,
16+
SOURCE_FORMATTERS_ID_ORIGIN,
1617
FEATURE_VISIBLE_PROPERTY_NAME,
1718
EMPTY_FEATURE_COLLECTION,
1819
LAYER_TYPE,
@@ -24,7 +25,11 @@ import { JoinTooltipProperty } from './tooltips/join_tooltip_property';
2425
import { EuiIcon } from '@elastic/eui';
2526
import { i18n } from '@kbn/i18n';
2627
import { DataRequestAbortError } from './util/data_request';
27-
import { canSkipSourceUpdate, canSkipStyleMetaUpdate } from './util/can_skip_fetch';
28+
import {
29+
canSkipSourceUpdate,
30+
canSkipStyleMetaUpdate,
31+
canSkipFormattersUpdate,
32+
} from './util/can_skip_fetch';
2833
import { assignFeatureIds } from './util/assign_feature_ids';
2934
import {
3035
getFillFilterExpression,
@@ -220,7 +225,7 @@ export class VectorLayer extends AbstractLayer {
220225
return indexPatternIds;
221226
}
222227

223-
_findDataRequestForSource(sourceDataId) {
228+
_findDataRequestById(sourceDataId) {
224229
return this._dataRequests.find(dataRequest => dataRequest.getDataId() === sourceDataId);
225230
}
226231

@@ -241,7 +246,7 @@ export class VectorLayer extends AbstractLayer {
241246
sourceQuery: joinSource.getWhereQuery(),
242247
applyGlobalQuery: joinSource.getApplyGlobalQuery(),
243248
};
244-
const prevDataRequest = this._findDataRequestForSource(sourceDataId);
249+
const prevDataRequest = this._findDataRequestById(sourceDataId);
245250

246251
const canSkipFetch = await canSkipSourceUpdate({
247252
source: joinSource,
@@ -286,6 +291,7 @@ export class VectorLayer extends AbstractLayer {
286291
async _syncJoins(syncContext) {
287292
const joinSyncs = this.getValidJoins().map(async join => {
288293
await this._syncJoinStyleMeta(syncContext, join);
294+
await this._syncJoinFormatters(syncContext, join);
289295
return this._syncJoin({ join, ...syncContext });
290296
});
291297

@@ -355,7 +361,7 @@ export class VectorLayer extends AbstractLayer {
355361
registerCancelCallback,
356362
dataFilters,
357363
}) {
358-
const requestToken = Symbol(`layer-source-data:${this.getId()}`);
364+
const requestToken = Symbol(`layer-${this.getId()}-${SOURCE_DATA_ID_ORIGIN}`);
359365
const searchFilters = this._getSearchFilters(dataFilters);
360366
const prevDataRequest = this.getSourceDataRequest();
361367

@@ -459,13 +465,13 @@ export class VectorLayer extends AbstractLayer {
459465
isTimeAware: this._style.isTimeAware() && (await source.isTimeAware()),
460466
timeFilters: dataFilters.timeFilters,
461467
};
462-
const prevDataRequest = this._findDataRequestForSource(dataRequestId);
468+
const prevDataRequest = this._findDataRequestById(dataRequestId);
463469
const canSkipFetch = canSkipStyleMetaUpdate({ prevDataRequest, nextMeta });
464470
if (canSkipFetch) {
465471
return;
466472
}
467473

468-
const requestToken = Symbol(`layer-${this.getId()}-style-meta`);
474+
const requestToken = Symbol(`layer-${this.getId()}-${dataRequestId}`);
469475
try {
470476
startLoading(dataRequestId, requestToken, nextMeta);
471477
const layerName = await this.getDisplayName();
@@ -484,12 +490,87 @@ export class VectorLayer extends AbstractLayer {
484490
}
485491
}
486492

493+
async _syncSourceFormatters(syncContext) {
494+
if (this._style.constructor.type !== LAYER_STYLE_TYPE.VECTOR) {
495+
return;
496+
}
497+
498+
return this._syncFormatters({
499+
source: this._source,
500+
dataRequestId: SOURCE_FORMATTERS_ID_ORIGIN,
501+
fields: this._style
502+
.getDynamicPropertiesArray()
503+
.filter(dynamicStyleProp => {
504+
return dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.SOURCE;
505+
})
506+
.map(dynamicStyleProp => {
507+
return dynamicStyleProp.getField();
508+
}),
509+
...syncContext,
510+
});
511+
}
512+
513+
async _syncJoinFormatters(syncContext, join) {
514+
const joinSource = join.getRightJoinSource();
515+
return this._syncFormatters({
516+
source: joinSource,
517+
dataRequestId: join.getSourceFormattersDataRequestId(),
518+
fields: this._style
519+
.getDynamicPropertiesArray()
520+
.filter(dynamicStyleProp => {
521+
const matchingField = joinSource.getMetricFieldForName(
522+
dynamicStyleProp.getField().getName()
523+
);
524+
return dynamicStyleProp.getFieldOrigin() === FIELD_ORIGIN.JOIN && !!matchingField;
525+
})
526+
.map(dynamicStyleProp => {
527+
return dynamicStyleProp.getField();
528+
}),
529+
...syncContext,
530+
});
531+
}
532+
533+
async _syncFormatters({ source, dataRequestId, fields, startLoading, stopLoading, onLoadError }) {
534+
if (fields.length === 0) {
535+
return;
536+
}
537+
538+
const fieldNames = fields.map(field => {
539+
return field.getName();
540+
});
541+
const nextMeta = {
542+
fieldNames: _.uniq(fieldNames).sort(),
543+
};
544+
const prevDataRequest = this._findDataRequestById(dataRequestId);
545+
const canSkipUpdate = canSkipFormattersUpdate({ prevDataRequest, nextMeta });
546+
if (canSkipUpdate) {
547+
return;
548+
}
549+
550+
const requestToken = Symbol(`layer-${this.getId()}-${dataRequestId}`);
551+
try {
552+
startLoading(dataRequestId, requestToken, nextMeta);
553+
554+
const formatters = {};
555+
const promises = fields.map(async field => {
556+
const fieldName = field.getName();
557+
formatters[fieldName] = await source.getFieldFormatter(fieldName);
558+
});
559+
await Promise.all(promises);
560+
561+
stopLoading(dataRequestId, requestToken, formatters, nextMeta);
562+
} catch (error) {
563+
onLoadError(dataRequestId, requestToken, error.message);
564+
}
565+
}
566+
487567
async syncData(syncContext) {
488568
if (!this.isVisible() || !this.showAtZoomLevel(syncContext.dataFilters.zoom)) {
489569
return;
490570
}
491571

492572
await this._syncSourceStyleMeta(syncContext);
573+
await this._syncSourceFormatters(syncContext);
493574
const sourceResult = await this._syncSource(syncContext);
494575
if (
495576
!sourceResult.featureCollection ||

0 commit comments

Comments
 (0)