diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index cfceb3e8b422e..2aee6a0cf8498 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -45,10 +45,9 @@ export const API_ROOT_PATH = `/${GIS_API_PATH}`; export const MVT_GETTILE_API_PATH = 'mvt/getTile'; export const MVT_GETGRIDTILE_API_PATH = 'mvt/getGridTile'; export const MVT_SOURCE_LAYER_NAME = 'source_layer'; -// Identifies vector tile "too many features" feature. -// "too many features" feature is a box showing area that contains too many features for single ES search response -export const KBN_TOO_MANY_FEATURES_PROPERTY = '__kbn_too_many_features__'; -export const KBN_TOO_MANY_FEATURES_IMAGE_ID = '__kbn_too_many_features_image_id__'; +// Identifies "incomplete data" feature. +// "incomplete data" feature is a box showing an area where incomplete data is displayed +export const KBN_IS_INCOMPLETE_DATA_FEATURE = '__kbn_is_incomplete_data_feature__'; // Identifies centroid feature. // Centroids are a single point for representing lines, multiLines, polygons, and multiPolygons export const KBN_IS_CENTROID_FEATURE = '__kbn_is_centroid_feature__'; diff --git a/x-pack/plugins/maps/common/get_centroid_features.test.ts b/x-pack/plugins/maps/common/get_centroid_features.test.ts index d409c9b71a59a..26e62e3de13a8 100644 --- a/x-pack/plugins/maps/common/get_centroid_features.test.ts +++ b/x-pack/plugins/maps/common/get_centroid_features.test.ts @@ -60,7 +60,7 @@ test('should not create centroid for too many features polygon', () => { ], }, properties: { - __kbn_too_many_features__: true, + __kbn_is_incomplete_data_feature__: true, prop0: 'value0', prop1: 0.0, }, diff --git a/x-pack/plugins/maps/common/get_centroid_features.ts b/x-pack/plugins/maps/common/get_centroid_features.ts index f8dd897d24e02..349864dff522f 100644 --- a/x-pack/plugins/maps/common/get_centroid_features.ts +++ b/x-pack/plugins/maps/common/get_centroid_features.ts @@ -22,7 +22,7 @@ import { lineString, polygon } from '@turf/helpers'; import { GEO_JSON_TYPE, KBN_IS_CENTROID_FEATURE, - KBN_TOO_MANY_FEATURES_PROPERTY, + KBN_IS_INCOMPLETE_DATA_FEATURE, } from './constants'; export function getCentroidFeatures(featureCollection: FeatureCollection): Feature[] { @@ -31,7 +31,7 @@ export function getCentroidFeatures(featureCollection: FeatureCollection): Featu const feature = featureCollection.features[i]; // do not add centroid for kibana added features - if (feature.properties?.[KBN_TOO_MANY_FEATURES_PROPERTY]) { + if (feature.properties?.[KBN_IS_INCOMPLETE_DATA_FEATURE]) { continue; } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index ee1cda6eaee43..c7015c6598941 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -22,11 +22,10 @@ import { SOURCE_BOUNDS_DATA_REQUEST_ID, FEATURE_VISIBLE_PROPERTY_NAME, EMPTY_FEATURE_COLLECTION, - KBN_TOO_MANY_FEATURES_PROPERTY, + KBN_IS_INCOMPLETE_DATA_FEATURE, LAYER_TYPE, FIELD_ORIGIN, LAYER_STYLE_TYPE, - KBN_TOO_MANY_FEATURES_IMAGE_ID, FieldFormatter, VECTOR_SHAPE_TYPE, } from '../../../../common/constants'; @@ -937,7 +936,7 @@ export class VectorLayer extends AbstractLayer { const sourceId = this.getId(); const fillLayerId = this._getMbPolygonLayerId(); const lineLayerId = this._getMbLineLayerId(); - const tooManyFeaturesLayerId = this._getMbTooManyFeaturesLayerId(); + const incompleteDataLayerId = this._getMbIncompleteDataLayerId(); const hasJoins = this.hasJoins(); if (!mbMap.getLayer(fillLayerId)) { @@ -964,29 +963,25 @@ export class VectorLayer extends AbstractLayer { } mbMap.addLayer(mbLayer); } - if (!mbMap.getLayer(tooManyFeaturesLayerId)) { + if (!mbMap.getLayer(incompleteDataLayerId)) { const mbLayer: MbLayer = { - id: tooManyFeaturesLayerId, - type: 'fill', + id: incompleteDataLayerId, + type: 'line', source: sourceId, - paint: {}, + paint: { + 'line-color': 'red', + 'line-width': 4, + 'line-dasharray': [2, 1], + }, }; if (mvtSourceLayer) { mbLayer['source-layer'] = mvtSourceLayer; } mbMap.addLayer(mbLayer); - mbMap.setFilter(tooManyFeaturesLayerId, [ - '==', - ['get', KBN_TOO_MANY_FEATURES_PROPERTY], - true, - ]); - mbMap.setPaintProperty( - tooManyFeaturesLayerId, - 'fill-pattern', - KBN_TOO_MANY_FEATURES_IMAGE_ID - ); - mbMap.setPaintProperty(tooManyFeaturesLayerId, 'fill-opacity', this.getAlpha()); + mbMap.setFilter(incompleteDataLayerId, ['==', ['get', KBN_IS_INCOMPLETE_DATA_FEATURE], true]); + mbMap.setLayoutProperty(incompleteDataLayerId, 'line-join', 'bevel'); } + mbMap.setPaintProperty(incompleteDataLayerId, 'line-opacity', this.getAlpha() * 0.6); this.getCurrentStyle().setMBPaintProperties({ alpha: this.getAlpha(), @@ -1009,8 +1004,8 @@ export class VectorLayer extends AbstractLayer { mbMap.setFilter(lineLayerId, lineFilterExpr); } - this.syncVisibilityWithMb(mbMap, tooManyFeaturesLayerId); - mbMap.setLayerZoomRange(tooManyFeaturesLayerId, this.getMinZoom(), this.getMaxZoom()); + this.syncVisibilityWithMb(mbMap, incompleteDataLayerId); + mbMap.setLayerZoomRange(incompleteDataLayerId, this.getMinZoom(), this.getMaxZoom()); } _setMbCentroidProperties(mbMap: MbMap, mvtSourceLayer?: string) { @@ -1103,8 +1098,8 @@ export class VectorLayer extends AbstractLayer { return this.makeMbLayerId('fill'); } - _getMbTooManyFeaturesLayerId() { - return this.makeMbLayerId('toomanyfeatures'); + _getMbIncompleteDataLayerId() { + return this.makeMbLayerId('kbn_incomplete_data_features'); } getMbLayerIds() { @@ -1115,7 +1110,7 @@ export class VectorLayer extends AbstractLayer { this._getMbSymbolLayerId(), this._getMbLineLayerId(), this._getMbPolygonLayerId(), - this._getMbTooManyFeaturesLayerId(), + this._getMbIncompleteDataLayerId(), ]; } diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts index 6696140a5d852..ff814f917d739 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts @@ -277,7 +277,7 @@ describe('ESGeoGridSource', () => { expect(urlTemplateWithMeta.minSourceZoom).toBe(0); expect(urlTemplateWithMeta.maxSourceZoom).toBe(24); expect(urlTemplateWithMeta.urlTemplate).toBe( - "rootdir/api/maps/mvt/getGridTile;?x={x}&y={y}&z={z}&geometryFieldName=bar&index=undefined&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:())),'1':('0':size,'1':0),'2':('0':filter,'1':!((geo_bounding_box:(bar:(bottom_right:!(180,-82.67628),top_left:!(-180,82.67628)))))),'3':('0':query),'4':('0':index,'1':(fields:())),'5':('0':query,'1':(language:KQL,query:'',queryLastTriggeredAt:'2019-04-25T20:53:22.331Z')),'6':('0':aggs,'1':(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:bar))),geotile_grid:(bounds:!n,field:bar,precision:!n,shard_size:65535,size:65535))))))&requestType=heatmap&geoFieldType=geo_point" + "rootdir/api/maps/mvt/getGridTile;?x={x}&y={y}&z={z}&geometryFieldName=bar&index=undefined&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:())),'1':('0':size,'1':0),'2':('0':filter,'1':!((geo_bounding_box:(bar:(bottom_right:!(180,-82.67628),top_left:!(-180,82.67628)))))),'3':('0':query),'4':('0':index,'1':(fields:())),'5':('0':query,'1':(language:KQL,query:'',queryLastTriggeredAt:'2019-04-25T20:53:22.331Z')),'6':('0':aggs,'1':(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:bar))),geotile_grid:(bounds:!n,field:bar,precision:!n,shard_size:65535,size:65535))))))&requestType=heatmap" ); }); @@ -288,7 +288,7 @@ describe('ESGeoGridSource', () => { }); expect(urlTemplateWithMeta.urlTemplate).toBe( - "rootdir/api/maps/mvt/getGridTile;?x={x}&y={y}&z={z}&geometryFieldName=bar&index=undefined&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:())),'1':('0':size,'1':0),'2':('0':filter,'1':!((geo_bounding_box:(bar:(bottom_right:!(180,-82.67628),top_left:!(-180,82.67628)))))),'3':('0':query),'4':('0':index,'1':(fields:())),'5':('0':query,'1':(language:KQL,query:'',queryLastTriggeredAt:'2019-04-25T20:53:22.331Z')),'6':('0':aggs,'1':(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:bar))),geotile_grid:(bounds:!n,field:bar,precision:!n,shard_size:65535,size:65535))))))&requestType=heatmap&geoFieldType=geo_point&searchSessionId=1" + "rootdir/api/maps/mvt/getGridTile;?x={x}&y={y}&z={z}&geometryFieldName=bar&index=undefined&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:())),'1':('0':size,'1':0),'2':('0':filter,'1':!((geo_bounding_box:(bar:(bottom_right:!(180,-82.67628),top_left:!(-180,82.67628)))))),'3':('0':query),'4':('0':index,'1':(fields:())),'5':('0':query,'1':(language:KQL,query:'',queryLastTriggeredAt:'2019-04-25T20:53:22.331Z')),'6':('0':aggs,'1':(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:bar))),geotile_grid:(bounds:!n,field:bar,precision:!n,shard_size:65535,size:65535))))))&requestType=heatmap&searchSessionId=1" ); }); }); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx index 4715398dab97b..d136279fb9432 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx @@ -443,7 +443,6 @@ export class ESGeoGridSource extends AbstractESAggSource implements ITiledSingle `/${GIS_API_PATH}/${MVT_GETGRIDTILE_API_PATH}` ); - const geoField = await this._getGeoField(); const urlTemplate = `${mvtUrlServicePath}\ ?x={x}\ &y={y}\ @@ -451,8 +450,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements ITiledSingle &geometryFieldName=${this._descriptor.geoField}\ &index=${indexPattern.title}\ &requestBody=${risonDsl}\ -&requestType=${this._descriptor.requestType}\ -&geoFieldType=${geoField.type}`; +&requestType=${this._descriptor.requestType}`; return { layerName: this.getLayerName(), minSourceZoom: this.getMinZoom(), diff --git a/x-pack/plugins/maps/public/classes/util/mb_filter_expressions.ts b/x-pack/plugins/maps/public/classes/util/mb_filter_expressions.ts index 4526340d3d865..812955caba5ad 100644 --- a/x-pack/plugins/maps/public/classes/util/mb_filter_expressions.ts +++ b/x-pack/plugins/maps/public/classes/util/mb_filter_expressions.ts @@ -9,15 +9,19 @@ import { GEO_JSON_TYPE, FEATURE_VISIBLE_PROPERTY_NAME, KBN_IS_CENTROID_FEATURE, - KBN_TOO_MANY_FEATURES_PROPERTY, + KBN_IS_INCOMPLETE_DATA_FEATURE, } from '../../../common/constants'; -export const EXCLUDE_TOO_MANY_FEATURES_BOX = ['!=', ['get', KBN_TOO_MANY_FEATURES_PROPERTY], true]; +export const EXCLUDE_INCOMPLETE_DATA_FEATURES = [ + '!=', + ['get', KBN_IS_INCOMPLETE_DATA_FEATURE], + true, +]; const EXCLUDE_CENTROID_FEATURES = ['!=', ['get', KBN_IS_CENTROID_FEATURE], true]; const VISIBILITY_FILTER_CLAUSE = ['all', ['==', ['get', FEATURE_VISIBLE_PROPERTY_NAME], true]]; // Kibana features are features added by kibana that do not exist in real data -const EXCLUDE_KBN_FEATURES = ['all', EXCLUDE_TOO_MANY_FEATURES_BOX, EXCLUDE_CENTROID_FEATURES]; +const EXCLUDE_KBN_FEATURES = ['all', EXCLUDE_INCOMPLETE_DATA_FEATURES, EXCLUDE_CENTROID_FEATURES]; const CLOSED_SHAPE_MB_FILTER = [ ...EXCLUDE_KBN_FEATURES, diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index 25bd589cda658..fe121a6921c1c 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -28,12 +28,7 @@ import { getPreserveDrawingBuffer } from '../../kibana_services'; import { ILayer } from '../../classes/layers/layer'; import { MapSettings } from '../../reducers/map'; import { Goto } from '../../../common/descriptor_types'; -import { - DECIMAL_DEGREES_PRECISION, - KBN_TOO_MANY_FEATURES_IMAGE_ID, - RawValue, - ZOOM_PRECISION, -} from '../../../common/constants'; +import { DECIMAL_DEGREES_PRECISION, RawValue, ZOOM_PRECISION } from '../../../common/constants'; import { getGlyphUrl, isRetina } from '../../meta'; import { syncLayerOrder } from './sort_layers'; // @ts-expect-error @@ -201,14 +196,6 @@ export class MBMap extends Component { mbMap.addControl(new mapboxgl.NavigationControl({ showCompass: false }), 'top-left'); } - const tooManyFeaturesImageSrc = - 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAA7DgAAOw4BzLahgwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAARLSURBVHic7ZnPbxRVAMe/7735sWO3293ZlUItJsivCxEE0oTYRgu1FqTQoFSwKTYx8SAH/wHjj4vRozGGi56sMcW2UfqTEuOhppE0KJc2GIuKQFDY7qzdtrudX88D3YTUdFuQN8+k87ltZt7uZz958/bNLAGwBWsYKltANmEA2QKyCQPIFpBNGEC2gGzCALIFZBMGkC0gmzCAbAHZhAFkC8gmDCBbQDZhANkCslnzARQZH6oDpNs0D5UDSUIInePcOpPLfdfnODNBuwQWIAWwNOABwHZN0x8npE6hNLJ4DPWRyFSf40wE5VOEQPBjcR0g3YlE4ybGmtK+/1NzJtOZA/xSYwZMs3nG962T2ez3It2AANaA/kSidYuivOQBs5WM1fUnk6f0u+GXJUqIuUtVXx00zRbRfkIDfBqL7a1WlIYbjvNtTTr99jXXHVpH6dMjK0R4cXq6c9rzxjcx9sKX8XitSEdhAToMI7VP10/97fsTh7PZrgWAN1lW72KE2vOm2b5chDTgtWQyn93x/bEEIetEOQIC14CxVOr1CkKefH929t0v8vn0vcdGEoljGxXl4C3PGz2YyXy+AHARDqtByAxoUdWKBKV70r4/vvTLA0CjZfX+5nkDGxirKzUTgkBIgNaysh3gnF627R+XO+dQJvP1ddcdrmSsbtA020pF+CAW21qrqmUiXIUEqGRsIwD0FQq/lzqv0bJ6rrvucBVjzwyb5ivLRTiiaW+8VV7eIEBVTAANiIIQd9RxZlc6t9Gyem647vn1jD07ZJonl4sQASoevqmgABzwwHnJzc69PGdZ3X+47sgGxuqHTPPE0ggeVtg5/QeEBMhxPg1Aa1DV2GrHPG9ZXy1G2D+wNALn9jyQEeHKAJgP+033Kgrdqij7AFwZtu3bqx3XWShMHtV1o1pRGo4YxiNd+fyEB2DKdX/4aG5u0hbwcylkBryTy/3scT6zW9Nq7ndso2Wdvea6Q1WUHuiPx1/WAXLBcWZXun94UMRcAoD/p+ddTFK6u8MwUvc7vsmyem+67oVqVT0wkEgcF+FYRNhW+L25uX6f84XThtHxIBudE5bVY/t++jFVrU/dvVSFICzAqG3PX/S8rihj2/61qK1AOUB7ksl2jdLUL7Z9rvgcQQRCFsEi5wqFmw26XnhCUQ63GcZmCly95Lrzpca0G0byk3j8tEnpU1c975tmyxoU5QcE8EAEAM5WVOzfoarHAeC2749dcpzxMwsLv07Ztg0AOzVNf03Ttu/S9T2PMlbjc25fdpyutmx2TLRbIAEA4M1otKo1EjmaoHQn4ZwBgA/kAVAK6MXXdzxv/ONcrq/HcbJBeAUWoEizqsaORaPbKglZrxMSZZyrM76f/ovzWx/m85PFWREUgQf4v7Hm/xcIA8gWkE0YQLaAbMIAsgVkEwaQLSCbMIBsAdmEAWQLyCYMIFtANmEA2QKyCQPIFpDNmg/wD3OFdEybUvJjAAAAAElFTkSuQmCC'; - const tooManyFeaturesImage = new Image(); - tooManyFeaturesImage.onload = () => { - mbMap.addImage(KBN_TOO_MANY_FEATURES_IMAGE_ID, tooManyFeaturesImage); - }; - tooManyFeaturesImage.src = tooManyFeaturesImageSrc; - let emptyImage: HTMLImageElement; mbMap.on('styleimagemissing', (e: unknown) => { if (emptyImage) { diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.js b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.js index 85c4fb2bca794..ab63bcfa04721 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.js +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.js @@ -9,7 +9,7 @@ import _ from 'lodash'; import React from 'react'; import { FEATURE_ID_PROPERTY_NAME, LON_INDEX } from '../../../../common/constants'; import { TooltipPopover } from './tooltip_popover'; -import { EXCLUDE_TOO_MANY_FEATURES_BOX } from '../../../classes/util/mb_filter_expressions'; +import { EXCLUDE_INCOMPLETE_DATA_FEATURES } from '../../../classes/util/mb_filter_expressions'; function justifyAnchorLocation(mbLngLat, targetFeature) { let popupAnchorLocation = [mbLngLat.lng, mbLngLat.lat]; // default popup location to mouse location @@ -179,7 +179,7 @@ export class TooltipControl extends React.Component { ]; return this.props.mbMap.queryRenderedFeatures(mbBbox, { layers: mbLayerIds, - filter: EXCLUDE_TOO_MANY_FEATURES_BOX, + filter: EXCLUDE_INCOMPLETE_DATA_FEATURES, }); } diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 3116838d26fb5..1ba1d37ef0604 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -16,7 +16,7 @@ import { ES_GEO_FIELD_TYPE, FEATURE_ID_PROPERTY_NAME, GEOTILE_GRID_AGG_NAME, - KBN_TOO_MANY_FEATURES_PROPERTY, + KBN_IS_INCOMPLETE_DATA_FEATURE, MAX_ZOOM, MVT_SOURCE_LAYER_NAME, RENDER_AS, @@ -25,7 +25,7 @@ import { import { convertRegularRespToGeoJson, hitsToGeoJson } from '../../common/elasticsearch_util'; import { flattenHit } from './util'; -import { ESBounds, tile2lat, tile2long, tileToESBbox } from '../../common/geo_tile_utils'; +import { ESBounds, tileToESBbox } from '../../common/geo_tile_utils'; import { getCentroidFeatures } from '../../common/get_centroid_features'; export async function getGridTile({ @@ -38,7 +38,6 @@ export async function getGridTile({ z, requestBody = {}, requestType = RENDER_AS.POINT, - geoFieldType = ES_GEO_FIELD_TYPE.GEO_POINT, searchSessionId, }: { x: number; @@ -50,38 +49,16 @@ export async function getGridTile({ logger: Logger; requestBody: any; requestType: RENDER_AS; - geoFieldType: ES_GEO_FIELD_TYPE; searchSessionId?: string; }): Promise { - const esBbox: ESBounds = tileToESBbox(x, y, z); try { - let bboxFilter; - if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { - bboxFilter = { - geo_bounding_box: { - [geometryFieldName]: esBbox, - }, - }; - } else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { - const geojsonPolygon = tileToGeoJsonPolygon(x, y, z); - bboxFilter = { - geo_shape: { - [geometryFieldName]: { - shape: geojsonPolygon, - relation: 'INTERSECTS', - }, - }, - }; - } else { - throw new Error(`${geoFieldType} is not valid geo field-type`); - } - requestBody.query.bool.filter.push(bboxFilter); - + const tileBounds: ESBounds = tileToESBbox(x, y, z); + requestBody.query.bool.filter.push(getTileSpatialFilter(geometryFieldName, tileBounds)); requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.precision = Math.min( z + SUPER_FINE_ZOOM_DELTA, MAX_ZOOM ); - requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.bounds = esBbox; + requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.bounds = tileBounds; const response = await context .search!.search( @@ -132,37 +109,47 @@ export async function getTile({ geoFieldType: ES_GEO_FIELD_TYPE; searchSessionId?: string; }): Promise { - let features: Feature[]; try { - requestBody.query.bool.filter.push({ - geo_shape: { - [geometryFieldName]: { - shape: tileToGeoJsonPolygon(x, y, z), - relation: 'INTERSECTS', - }, - }, - }); + requestBody.query.bool.filter.push( + getTileSpatialFilter(geometryFieldName, tileToESBbox(x, y, z)) + ); const searchOptions = { sessionId: searchSessionId, }; - const countResponse = await context + const documentsResponse = await context .search!.search( { params: { index, - body: { - size: 0, - query: requestBody.query, - }, + body: requestBody, }, }, searchOptions ) .toPromise(); - if (countResponse.rawResponse.hits.total > requestBody.size) { + // Todo: pass in epochMillies-fields + const featureCollection = hitsToGeoJson( + documentsResponse.rawResponse.hits.hits, + (hit: Record) => { + return flattenHit(geometryFieldName, hit); + }, + geometryFieldName, + geoFieldType, + [] + ); + + // Correct system-fields. + for (let i = 0; i < featureCollection.features.length; i++) { + const props = featureCollection.features[i].properties; + if (props !== null) { + props[FEATURE_ID_PROPERTY_NAME] = featureCollection.features[i].id; + } + } + + if (documentsResponse.rawResponse.hits.total > requestBody.size) { // Generate "too many features"-bounds const bboxResponse = await context .search!.search( @@ -186,57 +173,18 @@ export async function getTile({ ) .toPromise(); - features = [ - { - type: 'Feature', - properties: { - [KBN_TOO_MANY_FEATURES_PROPERTY]: true, - }, - geometry: esBboxToGeoJsonPolygon( - bboxResponse.rawResponse.aggregations.data_bounds.bounds - ), + featureCollection.features.push({ + type: 'Feature', + properties: { + [KBN_IS_INCOMPLETE_DATA_FEATURE]: true, }, - ]; - } else { - const documentsResponse = await context - .search!.search( - { - params: { - index, - body: requestBody, - }, - }, - searchOptions - ) - .toPromise(); - - // Todo: pass in epochMillies-fields - const featureCollection = hitsToGeoJson( - documentsResponse.rawResponse.hits.hits, - (hit: Record) => { - return flattenHit(geometryFieldName, hit); - }, - geometryFieldName, - geoFieldType, - [] - ); - - features = featureCollection.features; - - // Correct system-fields. - for (let i = 0; i < features.length; i++) { - const props = features[i].properties; - if (props !== null) { - props[FEATURE_ID_PROPERTY_NAME] = features[i].id; - } - } + geometry: esBboxToGeoJsonPolygon( + bboxResponse.rawResponse.aggregations.data_bounds.bounds, + tileToESBbox(x, y, z) + ), + }); } - const featureCollection: FeatureCollection = { - features, - type: 'FeatureCollection', - }; - return createMvtTile(featureCollection, z, x, y); } catch (e) { logger.warn(`Cannot generate tile for ${z}/${x}/${y}: ${e.message}`); @@ -244,32 +192,31 @@ export async function getTile({ } } -function tileToGeoJsonPolygon(x: number, y: number, z: number): Polygon { - const wLon = tile2long(x, z); - const sLat = tile2lat(y + 1, z); - const eLon = tile2long(x + 1, z); - const nLat = tile2lat(y, z); - +function getTileSpatialFilter(geometryFieldName: string, tileBounds: ESBounds): unknown { return { - type: 'Polygon', - coordinates: [ - [ - [wLon, sLat], - [wLon, nLat], - [eLon, nLat], - [eLon, sLat], - [wLon, sLat], - ], - ], + geo_shape: { + [geometryFieldName]: { + shape: { + type: 'envelope', + // upper left and lower right points of the shape to represent a bounding rectangle in the format [[minLon, maxLat], [maxLon, minLat]] + coordinates: [ + [tileBounds.top_left.lon, tileBounds.top_left.lat], + [tileBounds.bottom_right.lon, tileBounds.bottom_right.lat], + ], + }, + relation: 'INTERSECTS', + }, + }, }; } -function esBboxToGeoJsonPolygon(esBounds: ESBounds): Polygon { - let minLon = esBounds.top_left.lon; - const maxLon = esBounds.bottom_right.lon; +function esBboxToGeoJsonPolygon(esBounds: ESBounds, tileBounds: ESBounds): Polygon { + // Intersecting geo_shapes may push bounding box outside of tile so need to clamp to tile bounds. + let minLon = Math.max(esBounds.top_left.lon, tileBounds.top_left.lon); + const maxLon = Math.min(esBounds.bottom_right.lon, tileBounds.bottom_right.lon); minLon = minLon > maxLon ? minLon - 360 : minLon; // fixes an ES bbox to straddle dateline - const minLat = esBounds.bottom_right.lat; - const maxLat = esBounds.top_left.lat; + const minLat = Math.max(esBounds.bottom_right.lat, tileBounds.bottom_right.lat); + const maxLat = Math.min(esBounds.top_left.lat, tileBounds.top_left.lat); return { type: 'Polygon', diff --git a/x-pack/plugins/maps/server/mvt/mvt_routes.ts b/x-pack/plugins/maps/server/mvt/mvt_routes.ts index 3e16176579586..a28b9830c491e 100644 --- a/x-pack/plugins/maps/server/mvt/mvt_routes.ts +++ b/x-pack/plugins/maps/server/mvt/mvt_routes.ts @@ -81,7 +81,6 @@ export function initMVTRoutes({ requestBody: schema.string(), index: schema.string(), requestType: schema.string(), - geoFieldType: schema.string(), searchSessionId: schema.maybe(schema.string()), }), }, @@ -104,7 +103,6 @@ export function initMVTRoutes({ index: query.index as string, requestBody: requestBodyDSL as any, requestType: query.requestType as RENDER_AS, - geoFieldType: query.geoFieldType as ES_GEO_FIELD_TYPE, searchSessionId: query.searchSessionId, }); diff --git a/x-pack/test/api_integration/apis/maps/get_grid_tile.js b/x-pack/test/api_integration/apis/maps/get_grid_tile.js index 6e75c00f5007c..e6ab24b78a603 100644 --- a/x-pack/test/api_integration/apis/maps/get_grid_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_grid_tile.js @@ -27,8 +27,7 @@ export default function ({ getService }) { &geometryFieldName=geo.coordinates\ &index=logstash-*\ &requestBody=(_source:(excludes:!()),aggs:(gridSplit:(aggs:(avg_of_bytes:(avg:(field:bytes)),gridCentroid:(geo_centroid:(field:geo.coordinates))),geotile_grid:(bounds:!n,field:geo.coordinates,precision:!n,shard_size:65535,size:65535))),fields:!((field:%27@timestamp%27,format:date_time),(field:%27relatedContent.article:modified_time%27,format:date_time),(field:%27relatedContent.article:published_time%27,format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((match_all:()),(range:(%27@timestamp%27:(format:strict_date_optional_time,gte:%272015-09-20T00:00:00.000Z%27,lte:%272015-09-20T01:00:00.000Z%27)))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(hour_of_day:(script:(lang:painless,source:%27doc[!%27@timestamp!%27].value.getHour()%27))),size:0,stored_fields:!(%27*%27))\ -&requestType=point\ -&geoFieldType=geo_point` +&requestType=point` ) .set('kbn-xsrf', 'kibana') .responseType('blob') @@ -55,8 +54,7 @@ export default function ({ getService }) { &geometryFieldName=geo.coordinates\ &index=logstash-*\ &requestBody=(_source:(excludes:!()),aggs:(gridSplit:(aggs:(avg_of_bytes:(avg:(field:bytes)),gridCentroid:(geo_centroid:(field:geo.coordinates))),geotile_grid:(bounds:!n,field:geo.coordinates,precision:!n,shard_size:65535,size:65535))),fields:!((field:%27@timestamp%27,format:date_time),(field:%27relatedContent.article:modified_time%27,format:date_time),(field:%27relatedContent.article:published_time%27,format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((match_all:()),(range:(%27@timestamp%27:(format:strict_date_optional_time,gte:%272015-09-20T00:00:00.000Z%27,lte:%272015-09-20T01:00:00.000Z%27)))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(hour_of_day:(script:(lang:painless,source:%27doc[!%27@timestamp!%27].value.getHour()%27))),size:0,stored_fields:!(%27*%27))\ -&requestType=grid\ -&geoFieldType=geo_point` +&requestType=grid` ) .set('kbn-xsrf', 'kibana') .responseType('blob') diff --git a/x-pack/test/api_integration/apis/maps/get_tile.js b/x-pack/test/api_integration/apis/maps/get_tile.js index 8ece77a5096f3..e3e600d98e841 100644 --- a/x-pack/test/api_integration/apis/maps/get_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_tile.js @@ -47,7 +47,7 @@ export default function ({ getService }) { expect(feature.loadGeometry()).to.eql([[{ x: 44, y: 2382 }]]); }); - it('should return vector tile containing bounds when count exceeds size', async () => { + it('should return vector tile containing incomplete data boundary when count exceeds size', async () => { const resp = await supertest // requestBody sets size=1 to force count exceeded .get( @@ -66,12 +66,12 @@ export default function ({ getService }) { const jsonTile = new VectorTile(new Protobuf(resp.body)); const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; - expect(layer.length).to.be(1); - const feature = layer.feature(0); + expect(layer.length).to.be(2); + const feature = layer.feature(1); expect(feature.type).to.be(3); expect(feature.extent).to.be(4096); expect(feature.id).to.be(undefined); - expect(feature.properties).to.eql({ __kbn_too_many_features__: true }); + expect(feature.properties).to.eql({ __kbn_is_incomplete_data_feature__: true }); expect(feature.loadGeometry()).to.eql([ [ { x: 44, y: 2382 }, diff --git a/x-pack/test/functional/apps/maps/index.js b/x-pack/test/functional/apps/maps/index.js index d76afb7ebdc24..dd20ed58afbc6 100644 --- a/x-pack/test/functional/apps/maps/index.js +++ b/x-pack/test/functional/apps/maps/index.js @@ -47,6 +47,7 @@ export default function ({ loadTestFile, getService }) { loadTestFile(require.resolve('./es_geo_grid_source')); loadTestFile(require.resolve('./es_pew_pew_source')); loadTestFile(require.resolve('./joins')); + loadTestFile(require.resolve('./mapbox_styles')); loadTestFile(require.resolve('./mvt_scaling')); loadTestFile(require.resolve('./mvt_super_fine')); loadTestFile(require.resolve('./add_layer_panel')); diff --git a/x-pack/test/functional/apps/maps/joins.js b/x-pack/test/functional/apps/maps/joins.js index 094f5335cd05f..49717016f9c60 100644 --- a/x-pack/test/functional/apps/maps/joins.js +++ b/x-pack/test/functional/apps/maps/joins.js @@ -7,8 +7,6 @@ import expect from '@kbn/expect'; -import { MAPBOX_STYLES } from './mapbox_styles'; - const JOIN_PROPERTY_NAME = '__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1'; const EXPECTED_JOIN_VALUES = { alpha: 10, @@ -18,10 +16,6 @@ const EXPECTED_JOIN_VALUES = { }; const VECTOR_SOURCE_ID = 'n1t6f'; -const CIRCLE_STYLE_LAYER_INDEX = 0; -const FILL_STYLE_LAYER_INDEX = 2; -const LINE_STYLE_LAYER_INDEX = 3; -const TOO_MANY_FEATURES_LAYER_INDEX = 4; export default function ({ getPageObjects, getService }) { const PageObjects = getPageObjects(['maps']); @@ -95,34 +89,6 @@ export default function ({ getPageObjects, getService }) { }); }); - it('should style fills, points, lines, and bounding-boxes independently', async () => { - const mapboxStyle = await PageObjects.maps.getMapboxStyle(); - const layersForVectorSource = mapboxStyle.layers.filter((mbLayer) => { - return mbLayer.id.startsWith(VECTOR_SOURCE_ID); - }); - - //circle layer for points - expect(layersForVectorSource[CIRCLE_STYLE_LAYER_INDEX]).to.eql(MAPBOX_STYLES.POINT_LAYER); - - //fill layer - expect(layersForVectorSource[FILL_STYLE_LAYER_INDEX]).to.eql(MAPBOX_STYLES.FILL_LAYER); - - //line layer for borders - expect(layersForVectorSource[LINE_STYLE_LAYER_INDEX]).to.eql(MAPBOX_STYLES.LINE_LAYER); - - //Too many features layer (this is a static style config) - expect(layersForVectorSource[TOO_MANY_FEATURES_LAYER_INDEX]).to.eql({ - id: 'n1t6f_toomanyfeatures', - type: 'fill', - source: 'n1t6f', - minzoom: 0, - maxzoom: 24, - filter: ['==', ['get', '__kbn_too_many_features__'], true], - layout: { visibility: 'visible' }, - paint: { 'fill-pattern': '__kbn_too_many_features_image_id__', 'fill-opacity': 0.75 }, - }); - }); - it('should flag only the joined features as visible', async () => { const mapboxStyle = await PageObjects.maps.getMapboxStyle(); const vectorSource = mapboxStyle.sources[VECTOR_SOURCE_ID]; diff --git a/x-pack/test/functional/apps/maps/mapbox_styles.js b/x-pack/test/functional/apps/maps/mapbox_styles.js index d4496f13b8bef..76e7c19bf82b0 100644 --- a/x-pack/test/functional/apps/maps/mapbox_styles.js +++ b/x-pack/test/functional/apps/maps/mapbox_styles.js @@ -5,176 +5,250 @@ * 2.0. */ -export const MAPBOX_STYLES = { - POINT_LAYER: { - id: 'n1t6f_circle', - type: 'circle', - source: 'n1t6f', - minzoom: 0, - maxzoom: 24, - filter: [ - 'all', - ['==', ['get', '__kbn_isvisibleduetojoin__'], true], - [ - 'all', - ['!=', ['get', '__kbn_too_many_features__'], true], - ['!=', ['get', '__kbn_is_centroid_feature__'], true], - ['any', ['==', ['geometry-type'], 'Point'], ['==', ['geometry-type'], 'MultiPoint']], - ], - ], - layout: { visibility: 'visible' }, - paint: { - 'circle-color': [ - 'interpolate', - ['linear'], - [ - 'coalesce', +import expect from '@kbn/expect'; + +export default function ({ getPageObjects, getService }) { + const PageObjects = getPageObjects(['maps']); + const inspector = getService('inspector'); + const security = getService('security'); + + describe('mapbox styles', () => { + let mapboxStyle; + before(async () => { + await security.testUser.setRoles( + ['global_maps_all', 'geoshape_data_reader', 'meta_for_geoshape_data_reader'], + false + ); + await PageObjects.maps.loadSavedMap('join example'); + mapboxStyle = await PageObjects.maps.getMapboxStyle(); + }); + + after(async () => { + await inspector.close(); + await security.testUser.restoreDefaults(); + }); + + it('should style circle layer as expected', async () => { + const layer = mapboxStyle.layers.find((mbLayer) => { + return mbLayer.id === 'n1t6f_circle'; + }); + expect(layer).to.eql({ + id: 'n1t6f_circle', + type: 'circle', + source: 'n1t6f', + minzoom: 0, + maxzoom: 24, + filter: [ + 'all', + ['==', ['get', '__kbn_isvisibleduetojoin__'], true], [ - 'case', - [ - '==', - ['feature-state', '__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1'], - null, - ], - 2, + 'all', + ['!=', ['get', '__kbn_is_incomplete_data_feature__'], true], + ['!=', ['get', '__kbn_is_centroid_feature__'], true], + ['any', ['==', ['geometry-type'], 'Point'], ['==', ['geometry-type'], 'MultiPoint']], + ], + ], + layout: { visibility: 'visible' }, + paint: { + 'circle-color': [ + 'interpolate', + ['linear'], [ - 'max', + 'coalesce', [ - 'min', + 'case', [ - 'to-number', + '==', [ 'feature-state', '__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1', ], + null, + ], + 2, + [ + 'max', + [ + 'min', + [ + 'to-number', + [ + 'feature-state', + '__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1', + ], + ], + 12, + ], + 3, ], - 12, ], - 3, + 2, ], + 2, + 'rgba(0,0,0,0)', + 3, + '#ecf1f7', + 4.125, + '#d9e3ef', + 5.25, + '#c5d5e7', + 6.375, + '#b2c7df', + 7.5, + '#9eb9d8', + 8.625, + '#8bacd0', + 9.75, + '#769fc8', + 10.875, + '#6092c0', ], - 2, - ], - 2, - 'rgba(0,0,0,0)', - 3, - '#ecf1f7', - 4.125, - '#d9e3ef', - 5.25, - '#c5d5e7', - 6.375, - '#b2c7df', - 7.5, - '#9eb9d8', - 8.625, - '#8bacd0', - 9.75, - '#769fc8', - 10.875, - '#6092c0', - ], - 'circle-opacity': 0.75, - 'circle-stroke-color': '#41937c', - 'circle-stroke-opacity': 0.75, - 'circle-stroke-width': 1, - 'circle-radius': 10, - }, - }, - FILL_LAYER: { - id: 'n1t6f_fill', - type: 'fill', - source: 'n1t6f', - minzoom: 0, - maxzoom: 24, - filter: [ - 'all', - ['==', ['get', '__kbn_isvisibleduetojoin__'], true], - [ - 'all', - ['!=', ['get', '__kbn_too_many_features__'], true], - ['!=', ['get', '__kbn_is_centroid_feature__'], true], - ['any', ['==', ['geometry-type'], 'Polygon'], ['==', ['geometry-type'], 'MultiPolygon']], - ], - ], - layout: { visibility: 'visible' }, - paint: { - 'fill-color': [ - 'interpolate', - ['linear'], - [ - 'coalesce', + 'circle-opacity': 0.75, + 'circle-stroke-color': '#41937c', + 'circle-stroke-opacity': 0.75, + 'circle-stroke-width': 1, + 'circle-radius': 10, + }, + }); + }); + + it('should style fill layer as expected', async () => { + const layer = mapboxStyle.layers.find((mbLayer) => { + return mbLayer.id === 'n1t6f_fill'; + }); + expect(layer).to.eql({ + id: 'n1t6f_fill', + type: 'fill', + source: 'n1t6f', + minzoom: 0, + maxzoom: 24, + filter: [ + 'all', + ['==', ['get', '__kbn_isvisibleduetojoin__'], true], [ - 'case', + 'all', + ['!=', ['get', '__kbn_is_incomplete_data_feature__'], true], + ['!=', ['get', '__kbn_is_centroid_feature__'], true], [ - '==', - ['feature-state', '__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1'], - null, + 'any', + ['==', ['geometry-type'], 'Polygon'], + ['==', ['geometry-type'], 'MultiPolygon'], ], - 2, + ], + ], + layout: { visibility: 'visible' }, + paint: { + 'fill-color': [ + 'interpolate', + ['linear'], [ - 'max', + 'coalesce', [ - 'min', + 'case', [ - 'to-number', + '==', [ 'feature-state', '__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1', ], + null, + ], + 2, + [ + 'max', + [ + 'min', + [ + 'to-number', + [ + 'feature-state', + '__kbnjoin__max_of_prop1__855ccb86-fe42-11e8-8eb2-f2801f1b9fd1', + ], + ], + 12, + ], + 3, ], - 12, ], - 3, + 2, + ], + 2, + 'rgba(0,0,0,0)', + 3, + '#ecf1f7', + 4.125, + '#d9e3ef', + 5.25, + '#c5d5e7', + 6.375, + '#b2c7df', + 7.5, + '#9eb9d8', + 8.625, + '#8bacd0', + 9.75, + '#769fc8', + 10.875, + '#6092c0', + ], + 'fill-opacity': 0.75, + }, + }); + }); + + it('should style fill layer as expected', async () => { + const layer = mapboxStyle.layers.find((mbLayer) => { + return mbLayer.id === 'n1t6f_line'; + }); + expect(layer).to.eql({ + id: 'n1t6f_line', + type: 'line', + source: 'n1t6f', + minzoom: 0, + maxzoom: 24, + filter: [ + 'all', + ['==', ['get', '__kbn_isvisibleduetojoin__'], true], + [ + 'all', + ['!=', ['get', '__kbn_is_incomplete_data_feature__'], true], + ['!=', ['get', '__kbn_is_centroid_feature__'], true], + [ + 'any', + ['==', ['geometry-type'], 'Polygon'], + ['==', ['geometry-type'], 'MultiPolygon'], + ['==', ['geometry-type'], 'LineString'], + ['==', ['geometry-type'], 'MultiLineString'], ], ], - 2, - ], - 2, - 'rgba(0,0,0,0)', - 3, - '#ecf1f7', - 4.125, - '#d9e3ef', - 5.25, - '#c5d5e7', - 6.375, - '#b2c7df', - 7.5, - '#9eb9d8', - 8.625, - '#8bacd0', - 9.75, - '#769fc8', - 10.875, - '#6092c0', - ], - 'fill-opacity': 0.75, - }, - }, - LINE_LAYER: { - id: 'n1t6f_line', - type: 'line', - source: 'n1t6f', - minzoom: 0, - maxzoom: 24, - filter: [ - 'all', - ['==', ['get', '__kbn_isvisibleduetojoin__'], true], - [ - 'all', - ['!=', ['get', '__kbn_too_many_features__'], true], - ['!=', ['get', '__kbn_is_centroid_feature__'], true], - [ - 'any', - ['==', ['geometry-type'], 'Polygon'], - ['==', ['geometry-type'], 'MultiPolygon'], - ['==', ['geometry-type'], 'LineString'], - ['==', ['geometry-type'], 'MultiLineString'], ], - ], - ], - layout: { visibility: 'visible' }, - paint: { 'line-color': '#41937c', 'line-opacity': 0.75, 'line-width': 1 }, - }, -}; + layout: { visibility: 'visible' }, + paint: { 'line-color': '#41937c', 'line-opacity': 0.75, 'line-width': 1 }, + }); + }); + + it('should style incomplete data layer as expected', async () => { + const layer = mapboxStyle.layers.find((mbLayer) => { + return mbLayer.id === 'n1t6f_kbn_incomplete_data_features'; + }); + expect(layer).to.eql({ + id: 'n1t6f_kbn_incomplete_data_features', + type: 'line', + source: 'n1t6f', + minzoom: 0, + maxzoom: 24, + filter: ['==', ['get', '__kbn_is_incomplete_data_feature__'], true], + layout: { + 'line-join': 'bevel', + visibility: 'visible', + }, + paint: { + 'line-color': 'red', + 'line-width': 4, + 'line-dasharray': [2, 1], + 'line-opacity': 0.44999999999999996, + }, + }); + }); + }); +} diff --git a/x-pack/test/functional/apps/maps/mvt_super_fine.js b/x-pack/test/functional/apps/maps/mvt_super_fine.js index 0f18ac8ac72e4..2ffd3742b02a3 100644 --- a/x-pack/test/functional/apps/maps/mvt_super_fine.js +++ b/x-pack/test/functional/apps/maps/mvt_super_fine.js @@ -33,7 +33,7 @@ export default function ({ getPageObjects, getService }) { //Source should be correct expect(mapboxStyle.sources[MB_VECTOR_SOURCE_ID].tiles[0]).to.equal( - "/api/maps/mvt/getGridTile?x={x}&y={y}&z={z}&geometryFieldName=geo.coordinates&index=logstash-*&requestBody=(_source:(excludes:!()),aggs:(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:geo.coordinates)),max_of_bytes:(max:(field:bytes))),geotile_grid:(bounds:!n,field:geo.coordinates,precision:!n,shard_size:65535,size:65535))),fields:!((field:'@timestamp',format:date_time),(field:'relatedContent.article:modified_time',format:date_time),(field:'relatedContent.article:published_time',format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((match_all:()),(range:('@timestamp':(format:strict_date_optional_time,gte:'2015-09-20T00:00:00.000Z',lte:'2015-09-20T01:00:00.000Z')))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(hour_of_day:(script:(lang:painless,source:'doc[!'@timestamp!'].value.getHour()'))),size:0,stored_fields:!('*'))&requestType=grid&geoFieldType=geo_point" + "/api/maps/mvt/getGridTile?x={x}&y={y}&z={z}&geometryFieldName=geo.coordinates&index=logstash-*&requestBody=(_source:(excludes:!()),aggs:(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:geo.coordinates)),max_of_bytes:(max:(field:bytes))),geotile_grid:(bounds:!n,field:geo.coordinates,precision:!n,shard_size:65535,size:65535))),fields:!((field:'@timestamp',format:date_time),(field:'relatedContent.article:modified_time',format:date_time),(field:'relatedContent.article:published_time',format:date_time),(field:utc_time,format:date_time)),query:(bool:(filter:!((match_all:()),(range:('@timestamp':(format:strict_date_optional_time,gte:'2015-09-20T00:00:00.000Z',lte:'2015-09-20T01:00:00.000Z')))),must:!(),must_not:!(),should:!())),runtime_mappings:(),script_fields:(hour_of_day:(script:(lang:painless,source:'doc[!'@timestamp!'].value.getHour()'))),size:0,stored_fields:!('*'))&requestType=grid" ); //Should correctly load meta for style-rule (sigma is set to 1, opacity to 1)