Skip to content

Commit

Permalink
[Maps] Update Map extent queries to use bounding box logic for both p…
Browse files Browse the repository at this point in the history
…oint and shape queries (elastic#93156)
  • Loading branch information
Aaron Caldwell committed Mar 2, 2021
1 parent 022bde7 commit 25dd188
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 155 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ export interface ESPolygonFilter {

export function createExtentFilter(
mapExtent: MapExtent,
geoFieldName: string,
geoFieldType: ES_GEO_FIELD_TYPE
geoFieldName: string
): ESPolygonFilter | ESGeoBoundingBoxFilter;

export function makeESBbox({ maxLat, maxLon, minLat, minLon }: MapExtent): ESBBox;
Original file line number Diff line number Diff line change
Expand Up @@ -280,37 +280,15 @@ export function makeESBbox({ maxLat, maxLon, minLat, minLon }) {
return esBbox;
}

function createGeoBoundBoxFilter({ maxLat, maxLon, minLat, minLon }, geoFieldName) {
const boundingBox = makeESBbox({ maxLat, maxLon, minLat, minLon });
export function createExtentFilter(mapExtent, geoFieldName) {
const boundingBox = makeESBbox(mapExtent);
return {
geo_bounding_box: {
[geoFieldName]: boundingBox,
},
};
}

export function createExtentFilter(mapExtent, geoFieldName, geoFieldType) {
ensureGeoField(geoFieldType);

// 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(mapExtent, geoFieldName);
}

return {
geo_shape: {
[geoFieldName]: {
shape: formatEnvelopeAsPolygon(mapExtent),
relation: ES_SPATIAL_RELATIONS.INTERSECTS,
},
},
};
}

export function createSpatialFilterWithGeometry({
preIndexedShape,
geometry,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,143 +389,99 @@ describe('geoShapeToGeometry', () => {
});

describe('createExtentFilter', () => {
describe('geo_point field', () => {
it('should return elasticsearch geo_bounding_box filter for geo_point field', () => {
const mapExtent = {
maxLat: 39,
maxLon: -83,
minLat: 35,
minLon: -89,
};
const filter = createExtentFilter(mapExtent, geoFieldName, 'geo_point');
expect(filter).toEqual({
geo_bounding_box: {
location: {
top_left: [-89, 39],
bottom_right: [-83, 35],
},
},
});
});

it('should clamp longitudes to -180 to 180 and latitudes to -90 to 90', () => {
const mapExtent = {
maxLat: 120,
maxLon: 200,
minLat: -100,
minLon: -190,
};
const filter = createExtentFilter(mapExtent, geoFieldName, 'geo_point');
expect(filter).toEqual({
geo_bounding_box: {
location: {
top_left: [-180, 89],
bottom_right: [180, -89],
},
it('should return elasticsearch geo_bounding_box filter', () => {
const mapExtent = {
maxLat: 39,
maxLon: -83,
minLat: 35,
minLon: -89,
};
const filter = createExtentFilter(mapExtent, geoFieldName);
expect(filter).toEqual({
geo_bounding_box: {
location: {
top_left: [-89, 39],
bottom_right: [-83, 35],
},
});
},
});
});

it('should make left longitude greater then right longitude when area crosses 180 meridian east to west', () => {
const mapExtent = {
maxLat: 39,
maxLon: 200,
minLat: 35,
minLon: 100,
};
const filter = createExtentFilter(mapExtent, geoFieldName, 'geo_point');
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],
},
it('should clamp longitudes to -180 to 180 and latitudes to -90 to 90', () => {
const mapExtent = {
maxLat: 120,
maxLon: 200,
minLat: -100,
minLon: -190,
};
const filter = createExtentFilter(mapExtent, geoFieldName);
expect(filter).toEqual({
geo_bounding_box: {
location: {
top_left: [-180, 89],
bottom_right: [180, -89],
},
});
},
});
});

it('should make left longitude greater then right longitude when area crosses 180 meridian west to east', () => {
const mapExtent = {
maxLat: 39,
maxLon: -100,
minLat: 35,
minLon: -200,
};
const filter = createExtentFilter(mapExtent, geoFieldName, 'geo_point');
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],
},
it('should make left longitude greater then right longitude when area crosses 180 meridian east to west', () => {
const mapExtent = {
maxLat: 39,
maxLon: 200,
minLat: 35,
minLon: 100,
};
const filter = createExtentFilter(mapExtent, geoFieldName);
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],
},
});
},
});
});

describe('geo_shape field', () => {
it('should return elasticsearch geo_shape filter', () => {
const mapExtent = {
maxLat: 39,
maxLon: -83,
minLat: 35,
minLon: -89,
};
const filter = createExtentFilter(mapExtent, geoFieldName, 'geo_shape');
expect(filter).toEqual({
geo_shape: {
location: {
relation: 'INTERSECTS',
shape: {
coordinates: [
[
[-89, 39],
[-89, 35],
[-83, 35],
[-83, 39],
[-89, 39],
],
],
type: 'Polygon',
},
},
it('should make left longitude greater then right longitude when area crosses 180 meridian west to east', () => {
const mapExtent = {
maxLat: 39,
maxLon: -100,
minLat: 35,
minLon: -200,
};
const filter = createExtentFilter(mapExtent, geoFieldName);
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],
},
});
},
});
});

it('should clamp longitudes to -180 to 180 when lonitude wraps globe', () => {
const mapExtent = {
maxLat: 39,
maxLon: 209,
minLat: 35,
minLon: -191,
};
const filter = createExtentFilter(mapExtent, geoFieldName, 'geo_shape');
expect(filter).toEqual({
geo_shape: {
location: {
relation: 'INTERSECTS',
shape: {
coordinates: [
[
[-180, 39],
[-180, 35],
[180, 35],
[180, 39],
[-180, 39],
],
],
type: 'Polygon',
},
},
it('should clamp longitudes to -180 to 180 when longitude wraps globe', () => {
const mapExtent = {
maxLat: 39,
maxLon: 209,
minLat: 35,
minLon: -191,
};
const filter = createExtentFilter(mapExtent, geoFieldName);
expect(filter).toEqual({
geo_bounding_box: {
location: {
top_left: [-180, 39],
bottom_right: [180, 35],
},
});
},
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import {
import { IVectorStyle } from '../../styles/vector/vector_style';
import { IDynamicStyleProperty } from '../../styles/vector/properties/dynamic_style_property';
import { IField } from '../../fields/field';
import { ES_GEO_FIELD_TYPE, FieldFormatter } from '../../../../common/constants';
import { FieldFormatter } from '../../../../common/constants';
import {
Adapters,
RequestResponder,
Expand Down Expand Up @@ -236,11 +236,7 @@ export class AbstractESSource extends AbstractVectorSource implements IESSource
typeof searchFilters.geogridPrecision === 'number'
? expandToTileBoundaries(searchFilters.buffer, searchFilters.geogridPrecision)
: searchFilters.buffer;
const extentFilter = createExtentFilter(
buffer,
geoField.name,
geoField.type as ES_GEO_FIELD_TYPE
);
const extentFilter = createExtentFilter(buffer, geoField.name);

// @ts-expect-error
allFilters.push(extentFilter);
Expand Down

0 comments on commit 25dd188

Please sign in to comment.