mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
- do not clone geometries when decoding results from ES - reduce number of object-allocations when decoding results
This commit is contained in:
parent
650c7d6d8e
commit
c6f89244f6
2 changed files with 49 additions and 38 deletions
|
@ -19,14 +19,16 @@ import { i18n } from '@kbn/i18n';
|
|||
*/
|
||||
export function hitsToGeoJson(hits, flattenHit, geoFieldName, geoFieldType) {
|
||||
const features = [];
|
||||
hits.forEach(hit => {
|
||||
const properties = flattenHit(hit);
|
||||
const tmpGeometriesAccumulator = [];
|
||||
|
||||
let geometries;
|
||||
for (let i = 0; i < hits.length; i++) {
|
||||
const properties = flattenHit(hits[i]);
|
||||
|
||||
tmpGeometriesAccumulator.length = 0;//truncate accumulator
|
||||
if (geoFieldType === 'geo_point') {
|
||||
geometries = geoPointToGeometry(properties[geoFieldName]);
|
||||
geoPointToGeometry(properties[geoFieldName], tmpGeometriesAccumulator);
|
||||
} else if (geoFieldType === 'geo_shape') {
|
||||
geometries = geoShapeToGeometry(properties[geoFieldName]);
|
||||
geoShapeToGeometry(properties[geoFieldName], tmpGeometriesAccumulator);
|
||||
} else {
|
||||
const errorMessage = i18n.translate('xpack.maps.elasticsearch_geo_utils.unsupportedFieldTypeErrorMessage', {
|
||||
defaultMessage: 'Unsupported field type, expected: geo_shape or geo_point, you provided: {geoFieldType}',
|
||||
|
@ -34,18 +36,18 @@ export function hitsToGeoJson(hits, flattenHit, geoFieldName, geoFieldType) {
|
|||
});
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
// don't include geometry field value in properties
|
||||
delete properties[geoFieldName];
|
||||
|
||||
return geometries.map(geometry => {
|
||||
//create new geojson Feature for every individual geojson geometry.
|
||||
for (let j = 0; j < tmpGeometriesAccumulator.length; j++) {
|
||||
features.push({
|
||||
type: 'Feature',
|
||||
geometry: geometry,
|
||||
geometry: tmpGeometriesAccumulator[j],
|
||||
properties: properties
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'FeatureCollection',
|
||||
|
@ -60,9 +62,9 @@ function pointGeometryFactory(lat, lon) {
|
|||
};
|
||||
}
|
||||
|
||||
export function geoPointToGeometry(value) {
|
||||
export function geoPointToGeometry(value, accumulator) {
|
||||
if (!value) {
|
||||
return [];
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
|
@ -77,12 +79,14 @@ export function geoPointToGeometry(value) {
|
|||
// Geo-point expressed as a string with the format: "lat,lon".
|
||||
const lat = parseFloat(commaSplit[0]);
|
||||
const lon = parseFloat(commaSplit[1]);
|
||||
return [pointGeometryFactory(lat, lon)];
|
||||
accumulator.push(pointGeometryFactory(lat, lon));
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof value === 'object' && _.has(value, 'lat') && _.has(value, 'lon')) {
|
||||
// Geo-point expressed as an object with the format: { lon, lat }
|
||||
return [pointGeometryFactory(value.lat, value.lon)];
|
||||
accumulator.push(pointGeometryFactory(value.lat, value.lon));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Array.isArray(value)) {
|
||||
|
@ -101,31 +105,27 @@ export function geoPointToGeometry(value) {
|
|||
// Geo-point expressed as an array with the format: [lon, lat]
|
||||
const lat = value[1];
|
||||
const lon = value[0];
|
||||
return [pointGeometryFactory(lat, lon)];
|
||||
accumulator.push(pointGeometryFactory(lat, lon));
|
||||
return;
|
||||
}
|
||||
|
||||
// Geo-point expressed as an array of values
|
||||
return value.reduce(
|
||||
(points, itemInValueArray) => {
|
||||
return points.concat(geoPointToGeometry(itemInValueArray));
|
||||
},
|
||||
[]
|
||||
);
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
geoPointToGeometry(value[i], accumulator);
|
||||
}
|
||||
}
|
||||
|
||||
export function geoShapeToGeometry(value) {
|
||||
export function geoShapeToGeometry(value, accumulator) {
|
||||
if (!value) {
|
||||
return [];
|
||||
return;
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
// value expressed as an array of values
|
||||
return value.reduce(
|
||||
(shapes, itemInValueArray) => {
|
||||
return shapes.concat(geoShapeToGeometry(itemInValueArray));
|
||||
},
|
||||
[]
|
||||
);
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
geoShapeToGeometry(value[i], accumulator);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO handle case where value is WKT and convert to geojson
|
||||
|
@ -136,13 +136,18 @@ export function geoShapeToGeometry(value) {
|
|||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
const geoJson = _.cloneDeep(value);
|
||||
const geoJson = {
|
||||
type: value.type,
|
||||
coordinates: value.coordinates
|
||||
};
|
||||
|
||||
// https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-shape.html#input-structure
|
||||
// For some unknown compatibility nightmarish reason, Elasticsearch types are not capitalized the same as geojson types
|
||||
// For example: 'LineString' geojson type is 'linestring' in elasticsearch
|
||||
// Convert feature types to geojson spec values
|
||||
switch (geoJson.type) {
|
||||
// Sometimes, the type in ES is capitalized correctly. Sometimes it is not. It depends on how the doc was ingested
|
||||
// The below is the correction in-place.
|
||||
switch (value.type) {
|
||||
case 'point':
|
||||
geoJson.type = 'Point';
|
||||
break;
|
||||
|
@ -170,7 +175,7 @@ export function geoShapeToGeometry(value) {
|
|||
throw new Error(`Unable to convert ${geoJson.type} geometry to geojson, not supported`);
|
||||
}
|
||||
|
||||
return [geoJson];
|
||||
accumulator.push(geoJson);
|
||||
}
|
||||
|
||||
const POLYGON_COORDINATES_EXTERIOR_INDEX = 0;
|
||||
|
|
|
@ -200,7 +200,8 @@ describe('geoPointToGeometry', () => {
|
|||
|
||||
it('Should convert value stored as geo-point string', () => {
|
||||
const value = `${lat},${lon}`;
|
||||
const points = geoPointToGeometry(value);
|
||||
const points = [];
|
||||
geoPointToGeometry(value, points);
|
||||
expect(points.length).toBe(1);
|
||||
expect(points[0].type).toBe('Point');
|
||||
expect(points[0].coordinates).toEqual([lon, lat]);
|
||||
|
@ -208,7 +209,8 @@ describe('geoPointToGeometry', () => {
|
|||
|
||||
it('Should convert value stored as geo-point array', () => {
|
||||
const value = [lon, lat];
|
||||
const points = geoPointToGeometry(value);
|
||||
const points = [];
|
||||
geoPointToGeometry(value, points);
|
||||
expect(points.length).toBe(1);
|
||||
expect(points[0].type).toBe('Point');
|
||||
expect(points[0].coordinates).toEqual([lon, lat]);
|
||||
|
@ -219,7 +221,8 @@ describe('geoPointToGeometry', () => {
|
|||
lat,
|
||||
lon,
|
||||
};
|
||||
const points = geoPointToGeometry(value);
|
||||
const points = [];
|
||||
geoPointToGeometry(value, points);
|
||||
expect(points.length).toBe(1);
|
||||
expect(points[0].type).toBe('Point');
|
||||
expect(points[0].coordinates).toEqual([lon, lat]);
|
||||
|
@ -235,7 +238,8 @@ describe('geoPointToGeometry', () => {
|
|||
},
|
||||
`${lat2},${lon2}`
|
||||
];
|
||||
const points = geoPointToGeometry(value);
|
||||
const points = [];
|
||||
geoPointToGeometry(value, points);
|
||||
expect(points.length).toBe(2);
|
||||
expect(points[0].coordinates).toEqual([lon, lat]);
|
||||
expect(points[1].coordinates).toEqual([lon2, lat2]);
|
||||
|
@ -249,7 +253,8 @@ describe('geoShapeToGeometry', () => {
|
|||
type: 'linestring',
|
||||
coordinates: coordinates
|
||||
};
|
||||
const shapes = geoShapeToGeometry(value);
|
||||
const shapes = [];
|
||||
geoShapeToGeometry(value, shapes);
|
||||
expect(shapes.length).toBe(1);
|
||||
expect(shapes[0].type).toBe('LineString');
|
||||
expect(shapes[0].coordinates).toEqual(coordinates);
|
||||
|
@ -268,7 +273,8 @@ describe('geoShapeToGeometry', () => {
|
|||
coordinates: pointCoordinates
|
||||
}
|
||||
];
|
||||
const shapes = geoShapeToGeometry(value);
|
||||
const shapes = [];
|
||||
geoShapeToGeometry(value, shapes);
|
||||
expect(shapes.length).toBe(2);
|
||||
expect(shapes[0].type).toBe('LineString');
|
||||
expect(shapes[0].coordinates).toEqual(linestringCoordinates);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue