[Maps] update geospatial filters to use geo_shape query for geo_point fields (#62966)

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Nathan Reese 2020-04-13 13:30:18 -06:00 committed by GitHub
parent e27526fd92
commit 301b795db6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 84 deletions

View file

@ -12,7 +12,6 @@ import DrawRectangle from 'mapbox-gl-draw-rectangle-mode';
import { DrawCircle } from './draw_circle';
import {
createDistanceFilterWithMeta,
createSpatialFilterWithBoundingBox,
createSpatialFilterWithGeometry,
getBoundingBoxGeometry,
roundCoordinates,
@ -84,23 +83,17 @@ export class DrawControl extends React.Component {
roundCoordinates(geometry.coordinates);
try {
const options = {
const filter = createSpatialFilterWithGeometry({
geometry:
this.props.drawState.drawType === DRAW_TYPE.BOUNDS
? getBoundingBoxGeometry(geometry)
: geometry,
indexPatternId: this.props.drawState.indexPatternId,
geoFieldName: this.props.drawState.geoFieldName,
geoFieldType: this.props.drawState.geoFieldType,
geometryLabel: this.props.drawState.geometryLabel,
relation: this.props.drawState.relation,
};
const filter =
this.props.drawState.drawType === DRAW_TYPE.BOUNDS
? createSpatialFilterWithBoundingBox({
...options,
geometry: getBoundingBoxGeometry(geometry),
})
: createSpatialFilterWithGeometry({
...options,
geometry,
});
});
this.props.addFilters([filter]);
} catch (error) {
// TODO notify user why filter was not created

View file

@ -231,28 +231,16 @@ function createGeoBoundBoxFilter(geometry, geoFieldName, filterProps = {}) {
};
}
function createGeoPolygonFilter(polygonCoordinates, geoFieldName, filterProps = {}) {
return {
geo_polygon: {
ignore_unmapped: true,
[geoFieldName]: {
points: polygonCoordinates[POLYGON_COORDINATES_EXTERIOR_INDEX].map(coordinatePair => {
return {
lon: coordinatePair[LON_INDEX],
lat: coordinatePair[LAT_INDEX],
};
}),
},
},
...filterProps,
};
}
export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) {
ensureGeoField(geoFieldType);
const safePolygon = convertMapExtentToPolygon(mapExtent);
// Extent filters are used to dynamically filter data for the current map view port.
// Continue to use geo_bounding_box queries for extent filters
// 1) geo_bounding_box queries are faster than polygon queries
// 2) geo_shape benefits of pre-indexed shapes and
// compatability across multi-indices with geo_point and geo_shape do not apply to this use case.
if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) {
return createGeoBoundBoxFilter(safePolygon, geoFieldName);
}
@ -267,15 +255,7 @@ export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) {
};
}
export function createSpatialFilterWithBoundingBox(options) {
return createGeometryFilterWithMeta({ ...options, isBoundingBox: true });
}
export function createSpatialFilterWithGeometry(options) {
return createGeometryFilterWithMeta(options);
}
function createGeometryFilterWithMeta({
export function createSpatialFilterWithGeometry({
preIndexedShape,
geometry,
geometryLabel,
@ -283,16 +263,16 @@ function createGeometryFilterWithMeta({
geoFieldName,
geoFieldType,
relation = ES_SPATIAL_RELATIONS.INTERSECTS,
isBoundingBox = false,
}) {
ensureGeoField(geoFieldType);
const relationLabel =
geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT
? i18n.translate('xpack.maps.es_geo_utils.shapeFilter.geoPointRelationLabel', {
defaultMessage: 'in',
})
: getEsSpatialRelationLabel(relation);
const isGeoPoint = geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT;
const relationLabel = isGeoPoint
? i18n.translate('xpack.maps.es_geo_utils.shapeFilter.geoPointRelationLabel', {
defaultMessage: 'in',
})
: getEsSpatialRelationLabel(relation);
const meta = {
type: SPATIAL_FILTER_TYPE,
negate: false,
@ -301,47 +281,24 @@ function createGeometryFilterWithMeta({
alias: `${geoFieldName} ${relationLabel} ${geometryLabel}`,
};
if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) {
const shapeQuery = {
relation,
};
const shapeQuery = {
// geo_shape query with geo_point field only supports intersects relation
relation: isGeoPoint ? ES_SPATIAL_RELATIONS.INTERSECTS : relation,
};
if (preIndexedShape) {
shapeQuery.indexed_shape = preIndexedShape;
} else {
shapeQuery.shape = geometry;
}
return {
meta,
geo_shape: {
ignore_unmapped: true,
[geoFieldName]: shapeQuery,
},
};
if (preIndexedShape) {
shapeQuery.indexed_shape = preIndexedShape;
} else {
shapeQuery.shape = geometry;
}
// geo_points supports limited geometry types
ensureGeometryType(geometry.type, [GEO_JSON_TYPE.POLYGON, GEO_JSON_TYPE.MULTI_POLYGON]);
if (geometry.type === GEO_JSON_TYPE.MULTI_POLYGON) {
return {
meta,
query: {
bool: {
should: geometry.coordinates.map(polygonCoordinates => {
return createGeoPolygonFilter(polygonCoordinates, geoFieldName);
}),
},
},
};
}
if (isBoundingBox) {
return createGeoBoundBoxFilter(geometry, geoFieldName, { meta });
}
return createGeoPolygonFilter(geometry.coordinates, geoFieldName, { meta });
return {
meta,
geo_shape: {
ignore_unmapped: true,
[geoFieldName]: shapeQuery,
},
};
}
export function createDistanceFilterWithMeta({