[Maps] avoid duplicated geometry in filter meta (#51133)

* [Maps] avoid duplicated geometry in filter meta

* clean up

* fix type error

* remove filterTypes from data shim and import directly from NP data plugin

* rename mapQueryDsl to mapSpatialFilter

* add unit test for mapSpatialFilter
This commit is contained in:
Nathan Reese 2019-11-21 15:46:00 -07:00 committed by GitHub
parent 8acfd4673c
commit a9258ffa5e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 140 additions and 1 deletions

View file

@ -48,4 +48,5 @@ export enum FILTERS {
RANGE = 'range',
GEO_BOUNDING_BOX = 'geo_bounding_box',
GEO_POLYGON = 'geo_polygon',
SPATIAL_FILTER = 'spatial_filter',
}

View file

@ -19,6 +19,7 @@
import { reduceRight } from 'lodash';
import { mapSpatialFilter } from './mappers/map_spatial_filter';
import { mapMatchAll } from './mappers/map_match_all';
import { mapPhrase } from './mappers/map_phrase';
import { mapPhrases } from './mappers/map_phrases';
@ -50,6 +51,7 @@ export function mapFilter(filter: esFilters.Filter) {
// that either handles the mapping operation or not
// and add it here. ProTip: These are executed in order listed
const mappers = [
mapSpatialFilter,
mapMatchAll,
mapRange,
mapPhrase,

View file

@ -0,0 +1,84 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { mapSpatialFilter } from './map_spatial_filter';
import { esFilters } from '../../../../../common';
describe('mapSpatialFilter()', () => {
test('should return the key for matching multi polygon filter', async () => {
const filter = {
meta: {
alias: 'my spatial filter',
type: esFilters.FILTERS.SPATIAL_FILTER,
} as esFilters.FilterMeta,
query: {
bool: {
should: [
{
geo_polygon: {
geoCoordinates: { points: [] },
},
},
],
},
},
} as esFilters.Filter;
const result = mapSpatialFilter(filter);
expect(result).toHaveProperty('key', 'query');
expect(result).toHaveProperty('value', '');
expect(result).toHaveProperty('type', esFilters.FILTERS.SPATIAL_FILTER);
});
test('should return the key for matching polygon filter', async () => {
const filter = {
meta: {
alias: 'my spatial filter',
type: esFilters.FILTERS.SPATIAL_FILTER,
} as esFilters.FilterMeta,
geo_polygon: {
geoCoordinates: { points: [] },
},
} as esFilters.Filter;
const result = mapSpatialFilter(filter);
expect(result).toHaveProperty('key', 'geo_polygon');
expect(result).toHaveProperty('value', '');
expect(result).toHaveProperty('type', esFilters.FILTERS.SPATIAL_FILTER);
});
test('should return undefined for none matching', async done => {
const filter = {
meta: {
alias: 'my spatial filter',
} as esFilters.FilterMeta,
geo_polygon: {
geoCoordinates: { points: [] },
},
} as esFilters.Filter;
try {
mapSpatialFilter(filter);
} catch (e) {
expect(e).toBe(filter);
done();
}
});
});

View file

@ -0,0 +1,40 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { esFilters } from '../../../../../common';
// Use mapSpatialFilter mapper to avoid bloated meta with value and params for spatial filters.
export const mapSpatialFilter = (filter: esFilters.Filter) => {
const metaProperty = /(^\$|meta)/;
const key = Object.keys(filter).find(item => {
return !item.match(metaProperty);
});
if (
key &&
filter.meta &&
filter.meta.alias &&
filter.meta.type === esFilters.FILTERS.SPATIAL_FILTER
) {
return {
key,
type: filter.meta.type,
value: '',
};
}
throw filter;
};

View file

@ -14,6 +14,9 @@ import { GeometryFilterForm } from '../../../components/geometry_filter_form';
import { UrlOverflowService } from 'ui/error_url_overflow';
import rison from 'rison-node';
// over estimated and imprecise value to ensure filter has additional room for any meta keys added when filter is mapped.
const META_OVERHEAD = 100;
const urlOverflow = new UrlOverflowService();
export class FeatureGeometryFilterForm extends Component {
@ -70,7 +73,7 @@ export class FeatureGeometryFilterForm extends Component {
// Ensure filter will not overflow URL. Filters that contain geometry can be extremely large.
// No elasticsearch support for pre-indexed shapes and geo_point spatial queries.
if (window.location.href.length + rison.encode(filter).length > urlOverflow.failLength()) {
if (window.location.href.length + rison.encode(filter).length + META_OVERHEAD > urlOverflow.failLength()) {
this.setState({
errorMsg: i18n.translate('xpack.maps.tooltip.geometryFilterForm.filterTooLargeMessage', {
defaultMessage: 'Cannot create filter. Filters are added to the URL, and this shape has too many vertices to fit in the URL.'

View file

@ -18,6 +18,7 @@ import {
LAT_INDEX,
} from '../common/constants';
import { getEsSpatialRelationLabel } from '../common/i18n_getters';
import { SPATIAL_FILTER_TYPE } from './kibana_services';
function ensureGeoField(type) {
const expectedTypes = [ES_GEO_FIELD_TYPE.GEO_POINT, ES_GEO_FIELD_TYPE.GEO_SHAPE];
@ -287,6 +288,7 @@ function createGeometryFilterWithMeta({
})
: getEsSpatialRelationLabel(relation);
const meta = {
type: SPATIAL_FILTER_TYPE,
negate: false,
index: indexPatternId,
alias: `${geoFieldName} ${relationLabel} ${geometryLabel}`

View file

@ -6,6 +6,11 @@
jest.mock('ui/new_platform');
jest.mock('ui/index_patterns');
jest.mock('./kibana_services', () => {
return {
SPATIAL_FILTER_TYPE: 'spatial_filter'
};
});
import {
hitsToGeoJson,

View file

@ -7,7 +7,9 @@
import { getRequestInspectorStats, getResponseInspectorStats } from 'ui/courier/utils/courier_inspector_utils';
export { xpackInfo } from 'plugins/xpack_main/services/xpack_info';
import { start as data } from '../../../../../src/legacy/core_plugins/data/public/legacy';
import { esFilters } from '../../../../../src/plugins/data/public';
export const SPATIAL_FILTER_TYPE = esFilters.FILTERS.SPATIAL_FILTER;
export { SearchSource } from 'ui/courier';
export const indexPatternService = data.indexPatterns.indexPatterns;