[Maps] convert elasticsearch_utils to TS (#93984)

* [Maps] convert elasticsearch_utils to TS

* tslint

* clean up

* i18n cleanup

* update elasticsearch_geo_utils tests

* fix unit test

* review feedback

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Nathan Reese 2021-03-10 13:23:42 -07:00 committed by GitHub
parent ebd92a6e5d
commit 6264c563d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 194 additions and 166 deletions

View file

@ -131,15 +131,15 @@ export enum ES_SPATIAL_RELATIONS {
WITHIN = 'WITHIN',
}
export const GEO_JSON_TYPE = {
POINT: 'Point',
MULTI_POINT: 'MultiPoint',
LINE_STRING: 'LineString',
MULTI_LINE_STRING: 'MultiLineString',
POLYGON: 'Polygon',
MULTI_POLYGON: 'MultiPolygon',
GEOMETRY_COLLECTION: 'GeometryCollection',
};
export enum GEO_JSON_TYPE {
POINT = 'Point',
MULTI_POINT = 'MultiPoint',
LINE_STRING = 'LineString',
MULTI_LINE_STRING = 'MultiLineString',
POLYGON = 'Polygon',
MULTI_POLYGON = 'MultiPolygon',
GEOMETRY_COLLECTION = 'GeometryCollection',
}
export const POLYGON_COORDINATES_EXTERIOR_INDEX = 0;
export const LON_INDEX = 0;

View file

@ -1,53 +0,0 @@
/*
* 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 { FeatureCollection, GeoJsonProperties, Polygon } from 'geojson';
import { MapExtent } from '../descriptor_types';
import { ES_GEO_FIELD_TYPE, ES_SPATIAL_RELATIONS } from '../constants';
export function scaleBounds(bounds: MapExtent, scaleFactor: number): MapExtent;
export function turfBboxToBounds(turfBbox: unknown): MapExtent;
export function clampToLatBounds(lat: number): number;
export function clampToLonBounds(lon: number): number;
export function hitsToGeoJson(
hits: Array<Record<string, unknown>>,
flattenHit: (elasticSearchHit: Record<string, unknown>) => GeoJsonProperties,
geoFieldName: string,
geoFieldType: ES_GEO_FIELD_TYPE,
epochMillisFields: string[]
): FeatureCollection;
export interface ESBBox {
top_left: number[];
bottom_right: number[];
}
export interface ESGeoBoundingBoxFilter {
geo_bounding_box: {
[geoFieldName: string]: ESBBox;
};
}
export interface ESPolygonFilter {
geo_shape: {
[geoFieldName: string]: {
shape: Polygon;
relation: ES_SPATIAL_RELATIONS.INTERSECTS;
};
};
}
export function createExtentFilter(
mapExtent: MapExtent,
geoFieldName: string
): ESPolygonFilter | ESGeoBoundingBoxFilter;
export function makeESBbox({ maxLat, maxLon, minLat, minLon }: MapExtent): ESBBox;

View file

@ -397,12 +397,10 @@ describe('createExtentFilter', () => {
minLon: -89,
};
const filter = createExtentFilter(mapExtent, geoFieldName);
expect(filter).toEqual({
geo_bounding_box: {
location: {
top_left: [-89, 39],
bottom_right: [-83, 35],
},
expect(filter.geo_bounding_box).toEqual({
location: {
top_left: [-89, 39],
bottom_right: [-83, 35],
},
});
});
@ -415,12 +413,10 @@ describe('createExtentFilter', () => {
minLon: -190,
};
const filter = createExtentFilter(mapExtent, geoFieldName);
expect(filter).toEqual({
geo_bounding_box: {
location: {
top_left: [-180, 89],
bottom_right: [180, -89],
},
expect(filter.geo_bounding_box).toEqual({
location: {
top_left: [-180, 89],
bottom_right: [180, -89],
},
});
});
@ -436,12 +432,10 @@ describe('createExtentFilter', () => {
const leftLon = filter.geo_bounding_box.location.top_left[0];
const rightLon = filter.geo_bounding_box.location.bottom_right[0];
expect(leftLon).toBeGreaterThan(rightLon);
expect(filter).toEqual({
geo_bounding_box: {
location: {
top_left: [100, 39],
bottom_right: [-160, 35],
},
expect(filter.geo_bounding_box).toEqual({
location: {
top_left: [100, 39],
bottom_right: [-160, 35],
},
});
});
@ -457,12 +451,10 @@ describe('createExtentFilter', () => {
const leftLon = filter.geo_bounding_box.location.top_left[0];
const rightLon = filter.geo_bounding_box.location.bottom_right[0];
expect(leftLon).toBeGreaterThan(rightLon);
expect(filter).toEqual({
geo_bounding_box: {
location: {
top_left: [160, 39],
bottom_right: [-100, 35],
},
expect(filter.geo_bounding_box).toEqual({
location: {
top_left: [160, 39],
bottom_right: [-100, 35],
},
});
});
@ -475,12 +467,10 @@ describe('createExtentFilter', () => {
minLon: -191,
};
const filter = createExtentFilter(mapExtent, geoFieldName);
expect(filter).toEqual({
geo_bounding_box: {
location: {
top_left: [-180, 39],
bottom_right: [180, 35],
},
expect(filter.geo_bounding_box).toEqual({
location: {
top_left: [-180, 39],
bottom_right: [180, 35],
},
});
});

View file

@ -7,7 +7,12 @@
import _ from 'lodash';
import { i18n } from '@kbn/i18n';
// @ts-expect-error
import { parse } from 'wellknown';
// @ts-expect-error
import turfCircle from '@turf/circle';
import { Feature, FeatureCollection, Geometry, Polygon, Point, Position } from 'geojson';
import { BBox } from '@turf/helpers';
import {
DECIMAL_DEGREES_PRECISION,
ES_GEO_FIELD_TYPE,
@ -18,14 +23,54 @@ import {
LAT_INDEX,
} from '../constants';
import { getEsSpatialRelationLabel } from '../i18n_getters';
import { FILTERS } from '../../../../../src/plugins/data/common';
import turfCircle from '@turf/circle';
import { Filter, FILTERS } from '../../../../../src/plugins/data/common';
import { MapExtent } from '../descriptor_types';
const SPATIAL_FILTER_TYPE = FILTERS.SPATIAL_FILTER;
function ensureGeoField(type) {
type Coordinates = Position | Position[] | Position[][] | Position[][][];
// Elasticsearch stores more then just GeoJSON.
// 1) geometry.type as lower case string
// 2) circle and envelope types
interface ESGeometry {
type: string;
coordinates: Coordinates;
}
export interface ESBBox {
top_left: number[];
bottom_right: number[];
}
interface GeoShapeQueryBody {
shape?: Polygon;
relation?: ES_SPATIAL_RELATIONS;
indexed_shape?: PreIndexedShape;
}
export type GeoFilter = Filter & {
geo_bounding_box?: {
[geoFieldName: string]: ESBBox;
};
geo_distance?: {
distance: string;
[geoFieldName: string]: Position | { lat: number; lon: number } | string;
};
geo_shape?: {
[geoFieldName: string]: GeoShapeQueryBody;
};
};
export interface PreIndexedShape {
index: string;
id: string | number;
path: string;
}
function ensureGeoField(type: string) {
const expectedTypes = [ES_GEO_FIELD_TYPE.GEO_POINT, ES_GEO_FIELD_TYPE.GEO_SHAPE];
if (!expectedTypes.includes(type)) {
if (!expectedTypes.includes(type as ES_GEO_FIELD_TYPE)) {
const errorMessage = i18n.translate(
'xpack.maps.es_geo_utils.unsupportedFieldTypeErrorMessage',
{
@ -41,8 +86,8 @@ function ensureGeoField(type) {
}
}
function ensureGeometryType(type, expectedTypes) {
if (!expectedTypes.includes(type)) {
function ensureGeometryType(type: string, expectedTypes: GEO_JSON_TYPE[]) {
if (!expectedTypes.includes(type as GEO_JSON_TYPE)) {
const errorMessage = i18n.translate(
'xpack.maps.es_geo_utils.unsupportedGeometryTypeErrorMessage',
{
@ -68,36 +113,48 @@ function ensureGeometryType(type, expectedTypes) {
* @param {string} geoFieldType Geometry field type ["geo_point", "geo_shape"]
* @returns {number}
*/
export function hitsToGeoJson(hits, flattenHit, geoFieldName, geoFieldType, epochMillisFields) {
const features = [];
const tmpGeometriesAccumulator = [];
export function hitsToGeoJson(
hits: Array<Record<string, unknown>>,
flattenHit: (elasticSearchHit: Record<string, unknown>) => Record<string, unknown>,
geoFieldName: string,
geoFieldType: ES_GEO_FIELD_TYPE,
epochMillisFields: string[]
): FeatureCollection {
const features: Feature[] = [];
const tmpGeometriesAccumulator: Geometry[] = [];
for (let i = 0; i < hits.length; i++) {
const properties = flattenHit(hits[i]);
tmpGeometriesAccumulator.length = 0; //truncate accumulator
tmpGeometriesAccumulator.length = 0; // truncate accumulator
ensureGeoField(geoFieldType);
if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) {
geoPointToGeometry(properties[geoFieldName], tmpGeometriesAccumulator);
geoPointToGeometry(
properties[geoFieldName] as string | string[] | undefined,
tmpGeometriesAccumulator
);
} else {
geoShapeToGeometry(properties[geoFieldName], tmpGeometriesAccumulator);
geoShapeToGeometry(
properties[geoFieldName] as string | string[] | ESGeometry | ESGeometry[] | undefined,
tmpGeometriesAccumulator
);
}
// There is a bug in Elasticsearch API where epoch_millis are returned as a string instead of a number
// https://github.com/elastic/elasticsearch/issues/50622
// Convert these field values to integers.
for (let i = 0; i < epochMillisFields.length; i++) {
const fieldName = epochMillisFields[i];
for (let k = 0; k < epochMillisFields.length; k++) {
const fieldName = epochMillisFields[k];
if (typeof properties[fieldName] === 'string') {
properties[fieldName] = parseInt(properties[fieldName]);
properties[fieldName] = parseInt(properties[fieldName] as string, 10);
}
}
// don't include geometry field value in properties
delete properties[geoFieldName];
//create new geojson Feature for every individual geojson geometry.
// create new geojson Feature for every individual geojson geometry.
for (let j = 0; j < tmpGeometriesAccumulator.length; j++) {
features.push({
type: 'Feature',
@ -112,7 +169,7 @@ export function hitsToGeoJson(hits, flattenHit, geoFieldName, geoFieldType, epoc
return {
type: 'FeatureCollection',
features: features,
features,
};
}
@ -120,7 +177,10 @@ export function hitsToGeoJson(hits, flattenHit, geoFieldName, geoFieldType, epoc
// Either
// 1) Array of latLon strings
// 2) latLon string
export function geoPointToGeometry(value, accumulator) {
export function geoPointToGeometry(
value: string[] | string | undefined,
accumulator: Geometry[]
): void {
if (!value) {
return;
}
@ -138,10 +198,10 @@ export function geoPointToGeometry(value, accumulator) {
accumulator.push({
type: GEO_JSON_TYPE.POINT,
coordinates: [lon, lat],
});
} as Point);
}
export function convertESShapeToGeojsonGeometry(value) {
export function convertESShapeToGeojsonGeometry(value: ESGeometry): Geometry {
const geoJson = {
type: value.type,
coordinates: value.coordinates,
@ -183,12 +243,13 @@ export function convertESShapeToGeojsonGeometry(value) {
);
throw new Error(invalidGeometrycollectionError);
case 'envelope':
const envelopeCoords = geoJson.coordinates as Position[];
// format defined here https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-shape.html#_envelope
const polygon = formatEnvelopeAsPolygon({
minLon: geoJson.coordinates[0][0],
maxLon: geoJson.coordinates[1][0],
minLat: geoJson.coordinates[1][1],
maxLat: geoJson.coordinates[0][1],
minLon: envelopeCoords[0][0],
maxLon: envelopeCoords[1][0],
minLat: envelopeCoords[1][1],
maxLat: envelopeCoords[0][1],
});
geoJson.type = polygon.type;
geoJson.coordinates = polygon.coordinates;
@ -205,10 +266,10 @@ export function convertESShapeToGeojsonGeometry(value) {
);
throw new Error(errorMessage);
}
return geoJson;
return (geoJson as unknown) as Geometry;
}
function convertWKTStringToGeojson(value) {
function convertWKTStringToGeojson(value: string): Geometry {
try {
return parse(value);
} catch (e) {
@ -222,7 +283,10 @@ function convertWKTStringToGeojson(value) {
}
}
export function geoShapeToGeometry(value, accumulator) {
export function geoShapeToGeometry(
value: string | ESGeometry | string[] | ESGeometry[] | undefined,
accumulator: Geometry[]
): void {
if (!value) {
return;
}
@ -243,8 +307,9 @@ export function geoShapeToGeometry(value, accumulator) {
value.type === GEO_JSON_TYPE.GEOMETRY_COLLECTION ||
value.type === 'geometrycollection'
) {
for (let i = 0; i < value.geometries.length; i++) {
geoShapeToGeometry(value.geometries[i], accumulator);
const geometryCollection = (value as unknown) as { geometries: ESGeometry[] };
for (let i = 0; i < geometryCollection.geometries.length; i++) {
geoShapeToGeometry(geometryCollection.geometries[i], accumulator);
}
} else {
const geoJson = convertESShapeToGeojsonGeometry(value);
@ -252,7 +317,7 @@ export function geoShapeToGeometry(value, accumulator) {
}
}
export function makeESBbox({ maxLat, maxLon, minLat, minLon }) {
export function makeESBbox({ maxLat, maxLon, minLat, minLon }: MapExtent): ESBBox {
const bottom = clampToLatBounds(minLat);
const top = clampToLatBounds(maxLat);
let esBbox;
@ -280,11 +345,16 @@ export function makeESBbox({ maxLat, maxLon, minLat, minLon }) {
return esBbox;
}
export function createExtentFilter(mapExtent, geoFieldName) {
const boundingBox = makeESBbox(mapExtent);
export function createExtentFilter(mapExtent: MapExtent, geoFieldName: string): GeoFilter {
return {
geo_bounding_box: {
[geoFieldName]: boundingBox,
[geoFieldName]: makeESBbox(mapExtent),
},
meta: {
alias: null,
disabled: false,
negate: false,
key: geoFieldName,
},
};
}
@ -297,6 +367,14 @@ export function createSpatialFilterWithGeometry({
geoFieldName,
geoFieldType,
relation = ES_SPATIAL_RELATIONS.INTERSECTS,
}: {
preIndexedShape?: PreIndexedShape;
geometry: Polygon;
geometryLabel: string;
indexPatternId: string;
geoFieldName: string;
geoFieldType: ES_GEO_FIELD_TYPE;
relation: ES_SPATIAL_RELATIONS;
}) {
ensureGeoField(geoFieldType);
@ -315,7 +393,7 @@ export function createSpatialFilterWithGeometry({
alias: `${geoFieldName} ${relationLabel} ${geometryLabel}`,
};
const shapeQuery = {
const shapeQuery: GeoShapeQueryBody = {
// geo_shape query with geo_point field only supports intersects relation
relation: isGeoPoint ? ES_SPATIAL_RELATIONS.INTERSECTS : relation,
};
@ -341,6 +419,12 @@ export function createDistanceFilterWithMeta({
geoFieldName,
indexPatternId,
point,
}: {
alias: string;
distanceKm: number;
geoFieldName: string;
indexPatternId: string;
point: Position;
}) {
const meta = {
type: SPATIAL_FILTER_TYPE,
@ -368,7 +452,7 @@ export function createDistanceFilterWithMeta({
};
}
export function roundCoordinates(coordinates) {
export function roundCoordinates(coordinates: Coordinates): void {
for (let i = 0; i < coordinates.length; i++) {
const value = coordinates[i];
if (Array.isArray(value)) {
@ -382,10 +466,10 @@ export function roundCoordinates(coordinates) {
/*
* returns Polygon geometry where coordinates define a bounding box that contains the input geometry
*/
export function getBoundingBoxGeometry(geometry) {
export function getBoundingBoxGeometry(geometry: Geometry): Polygon {
ensureGeometryType(geometry.type, [GEO_JSON_TYPE.POLYGON]);
const exterior = geometry.coordinates[POLYGON_COORDINATES_EXTERIOR_INDEX];
const exterior = (geometry as Polygon).coordinates[POLYGON_COORDINATES_EXTERIOR_INDEX];
const extent = {
minLon: exterior[0][LON_INDEX],
minLat: exterior[0][LAT_INDEX],
@ -402,7 +486,7 @@ export function getBoundingBoxGeometry(geometry) {
return formatEnvelopeAsPolygon(extent);
}
export function formatEnvelopeAsPolygon({ maxLat, maxLon, minLat, minLon }) {
export function formatEnvelopeAsPolygon({ maxLat, maxLon, minLat, minLon }: MapExtent): Polygon {
// GeoJSON mandates that the outer polygon must be counterclockwise to avoid ambiguous polygons
// when the shape crosses the dateline
const lonDelta = maxLon - minLon;
@ -410,25 +494,25 @@ export function formatEnvelopeAsPolygon({ maxLat, maxLon, minLat, minLon }) {
const right = lonDelta > 360 ? 180 : maxLon;
const top = clampToLatBounds(maxLat);
const bottom = clampToLatBounds(minLat);
const topLeft = [left, top];
const bottomLeft = [left, bottom];
const bottomRight = [right, bottom];
const topRight = [right, top];
const topLeft = [left, top] as Position;
const bottomLeft = [left, bottom] as Position;
const bottomRight = [right, bottom] as Position;
const topRight = [right, top] as Position;
return {
type: GEO_JSON_TYPE.POLYGON,
coordinates: [[topLeft, bottomLeft, bottomRight, topRight, topLeft]],
};
} as Polygon;
}
export function clampToLatBounds(lat) {
export function clampToLatBounds(lat: number): number {
return clamp(lat, -89, 89);
}
export function clampToLonBounds(lon) {
export function clampToLonBounds(lon: number): number {
return clamp(lon, -180, 180);
}
export function clamp(val, min, max) {
export function clamp(val: number, min: number, max: number): number {
if (val > max) {
return max;
} else if (val < min) {
@ -438,25 +522,26 @@ export function clamp(val, min, max) {
}
}
export function extractFeaturesFromFilters(filters) {
const features = [];
export function extractFeaturesFromFilters(filters: GeoFilter[]): Feature[] {
const features: Feature[] = [];
filters
.filter((filter) => {
return filter.meta.key && filter.meta.type === SPATIAL_FILTER_TYPE;
})
.forEach((filter) => {
const geoFieldName = filter.meta.key!;
let geometry;
if (filter.geo_distance && filter.geo_distance[filter.meta.key]) {
if (filter.geo_distance && filter.geo_distance[geoFieldName]) {
const distanceSplit = filter.geo_distance.distance.split('km');
const distance = parseFloat(distanceSplit[0]);
const circleFeature = turfCircle(filter.geo_distance[filter.meta.key], distance);
const circleFeature = turfCircle(filter.geo_distance[geoFieldName], distance);
geometry = circleFeature.geometry;
} else if (
filter.geo_shape &&
filter.geo_shape[filter.meta.key] &&
filter.geo_shape[filter.meta.key].shape
filter.geo_shape[geoFieldName] &&
filter.geo_shape[geoFieldName].shape
) {
geometry = filter.geo_shape[filter.meta.key].shape;
geometry = filter.geo_shape[geoFieldName].shape;
} else {
// do not know how to convert spatial filter to geometry
// this includes pre-indexed shapes
@ -475,7 +560,7 @@ export function extractFeaturesFromFilters(filters) {
return features;
}
export function scaleBounds(bounds, scaleFactor) {
export function scaleBounds(bounds: MapExtent, scaleFactor: number): MapExtent {
const width = bounds.maxLon - bounds.minLon;
const height = bounds.maxLat - bounds.minLat;
return {
@ -486,7 +571,7 @@ export function scaleBounds(bounds, scaleFactor) {
};
}
export function turfBboxToBounds(turfBbox) {
export function turfBboxToBounds(turfBbox: BBox): MapExtent {
return {
minLon: turfBbox[0],
minLat: turfBbox[1],

View file

@ -7,7 +7,6 @@
import { i18n } from '@kbn/i18n';
import { $Values } from '@kbn/utility-types';
import { ES_SPATIAL_RELATIONS } from './constants';
export function getAppTitle() {
@ -34,7 +33,7 @@ export function getUrlLabel() {
});
}
export function getEsSpatialRelationLabel(spatialRelation: $Values<typeof ES_SPATIAL_RELATIONS>) {
export function getEsSpatialRelationLabel(spatialRelation: ES_SPATIAL_RELATIONS) {
switch (spatialRelation) {
case ES_SPATIAL_RELATIONS.INTERSECTS:
return i18n.translate('xpack.maps.common.esSpatialRelation.intersectsLabel', {

View file

@ -206,6 +206,12 @@ describe('ESGeoGridSource', () => {
expect(getProperty('filter')).toEqual([
{
geo_bounding_box: { bar: { bottom_right: [180, -82.67628], top_left: [-180, 82.67628] } },
meta: {
alias: null,
disabled: false,
key: 'bar',
negate: false,
},
},
]);
expect(getProperty('aggs')).toEqual({
@ -277,7 +283,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))),meta:(alias:!n,disabled:!f,key:bar,negate:!f)))),'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"
);
});
@ -288,7 +294,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))),meta:(alias:!n,disabled:!f,key:bar,negate:!f)))),'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"
);
});
});

View file

@ -14,7 +14,12 @@ import { IFieldType, IndexPattern } from 'src/plugins/data/public';
import { GeoJsonProperties } from 'geojson';
import { AbstractESSource } from '../es_source';
import { getHttp, getSearchService } from '../../../kibana_services';
import { addFieldToDSL, getField, hitsToGeoJson } from '../../../../common/elasticsearch_util';
import {
addFieldToDSL,
getField,
hitsToGeoJson,
PreIndexedShape,
} from '../../../../common/elasticsearch_util';
// @ts-expect-error
import { UpdateSourceEditor } from './update_source_editor';
@ -43,7 +48,7 @@ import {
VectorSourceSyncMeta,
} from '../../../../common/descriptor_types';
import { Adapters } from '../../../../../../../src/plugins/inspector/common/adapters';
import { ImmutableSourceProperty, PreIndexedShape, SourceEditorArgs } from '../source';
import { ImmutableSourceProperty, SourceEditorArgs } from '../source';
import { IField } from '../../fields/field';
import {
GeoJsonWithMeta,

View file

@ -238,7 +238,6 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource
: searchFilters.buffer;
const extentFilter = createExtentFilter(buffer, geoField.name);
// @ts-expect-error
allFilters.push(extentFilter);
}
if (searchFilters.applyGlobalTime && (await this.isTimeAware())) {

View file

@ -18,6 +18,7 @@ import { FieldFormatter, MAX_ZOOM, MIN_ZOOM } from '../../../common/constants';
import { AbstractSourceDescriptor } from '../../../common/descriptor_types';
import { OnSourceChangeArgs } from '../../connected_components/layer_panel/view';
import { LICENSED_FEATURES } from '../../licensed_features';
import { PreIndexedShape } from '../../../common/elasticsearch_util';
export type SourceEditorArgs = {
onChange: (...args: OnSourceChangeArgs[]) => void;
@ -35,12 +36,6 @@ export type Attribution = {
label: string;
};
export type PreIndexedShape = {
index: string;
id: string | number;
path: string;
};
export interface ISource {
destroy(): void;
getDisplayName(): Promise<string>;

View file

@ -12,10 +12,12 @@
// - only fields from the response are packed in the tile (more efficient)
// - query-dsl submitted from the client, which was generated by the IndexPattern
// todo: Ideally, this should adapt/reuse from https://github.com/elastic/kibana/blob/52b42a81faa9dd5c102b9fbb9a645748c3623121/src/plugins/data/common/index_patterns/index_patterns/flatten_hit.ts#L26
import { GeoJsonProperties } from 'geojson';
export function flattenHit(geometryField: string, hit: Record<string, unknown>): GeoJsonProperties {
const flat: GeoJsonProperties = {};
export function flattenHit(
geometryField: string,
hit: Record<string, unknown>
): Record<string, any> {
const flat: Record<string, any> = {};
if (hit) {
flattenSource(flat, '', hit._source as Record<string, unknown>, geometryField);
if (hit.fields) {
@ -30,11 +32,11 @@ export function flattenHit(geometryField: string, hit: Record<string, unknown>):
}
function flattenSource(
accum: GeoJsonProperties,
accum: Record<string, any>,
path: string,
properties: Record<string, unknown> = {},
geometryField: string
): GeoJsonProperties {
): Record<string, any> {
accum = accum || {};
for (const key in properties) {
if (properties.hasOwnProperty(key)) {
@ -58,7 +60,7 @@ function flattenSource(
return accum;
}
function flattenFields(accum: GeoJsonProperties = {}, fields: Array<Record<string, unknown>>) {
function flattenFields(accum: Record<string, any> = {}, fields: Array<Record<string, unknown>>) {
accum = accum || {};
for (const key in fields) {
if (fields.hasOwnProperty(key)) {