chore(Query): $withinPolygon: 3 point minimum and boundary testing. (#3889)
* added 3 point minimum constraint to within-polygon * test nit * test for open and closed paths
This commit is contained in:
committed by
Florent Vilmart
parent
9ad8697c7a
commit
e8be98ded2
@@ -5,6 +5,7 @@ const rp = require('request-promise');
|
|||||||
var TestObject = Parse.Object.extend('TestObject');
|
var TestObject = Parse.Object.extend('TestObject');
|
||||||
|
|
||||||
describe('Parse.GeoPoint testing', () => {
|
describe('Parse.GeoPoint testing', () => {
|
||||||
|
|
||||||
it('geo point roundtrip', (done) => {
|
it('geo point roundtrip', (done) => {
|
||||||
var point = new Parse.GeoPoint(44.0, -11.0);
|
var point = new Parse.GeoPoint(44.0, -11.0);
|
||||||
var obj = new TestObject();
|
var obj = new TestObject();
|
||||||
@@ -331,18 +332,20 @@ describe('Parse.GeoPoint testing', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('works with geobox queries', (done) => {
|
it('works with geobox queries', (done) => {
|
||||||
var inSF = new Parse.GeoPoint(37.75, -122.4);
|
const inbound = new Parse.GeoPoint(1.5, 1.5);
|
||||||
var southwestOfSF = new Parse.GeoPoint(37.708813, -122.526398);
|
const onbound = new Parse.GeoPoint(10, 10);
|
||||||
var northeastOfSF = new Parse.GeoPoint(37.822802, -122.373962);
|
const outbound = new Parse.GeoPoint(20, 20);
|
||||||
|
const obj1 = new Parse.Object('TestObject', {location: inbound});
|
||||||
var object = new TestObject();
|
const obj2 = new Parse.Object('TestObject', {location: onbound});
|
||||||
object.set('point', inSF);
|
const obj3 = new Parse.Object('TestObject', {location: outbound});
|
||||||
object.save().then(() => {
|
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
|
||||||
var query = new Parse.Query(TestObject);
|
const sw = new Parse.GeoPoint(0, 0);
|
||||||
query.withinGeoBox('point', southwestOfSF, northeastOfSF);
|
const ne = new Parse.GeoPoint(10, 10);
|
||||||
|
const query = new Parse.Query(TestObject);
|
||||||
|
query.withinGeoBox('location', sw, ne);
|
||||||
return query.find();
|
return query.find();
|
||||||
}).then((results) => {
|
}).then((results) => {
|
||||||
equal(results.length, 1);
|
equal(results.length, 2);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -407,13 +410,13 @@ describe('Parse.GeoPoint testing', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('supports withinPolygon', (done) => {
|
it('supports withinPolygon open path', (done) => {
|
||||||
const point1 = new Parse.GeoPoint(1.5, 1.5);
|
const inbound = new Parse.GeoPoint(1.5, 1.5);
|
||||||
const point2 = new Parse.GeoPoint(2, 8);
|
const onbound = new Parse.GeoPoint(10, 10);
|
||||||
const point3 = new Parse.GeoPoint(20, 20);
|
const outbound = new Parse.GeoPoint(20, 20);
|
||||||
const obj1 = new Parse.Object('Polygon', {location: point1});
|
const obj1 = new Parse.Object('Polygon', {location: inbound});
|
||||||
const obj2 = new Parse.Object('Polygon', {location: point2});
|
const obj2 = new Parse.Object('Polygon', {location: onbound});
|
||||||
const obj3 = new Parse.Object('Polygon', {location: point3});
|
const obj3 = new Parse.Object('Polygon', {location: outbound});
|
||||||
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
|
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
|
||||||
const where = {
|
const where = {
|
||||||
location: {
|
location: {
|
||||||
@@ -441,6 +444,41 @@ describe('Parse.GeoPoint testing', () => {
|
|||||||
}, done.fail);
|
}, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('supports withinPolygon closed path', (done) => {
|
||||||
|
const inbound = new Parse.GeoPoint(1.5, 1.5);
|
||||||
|
const onbound = new Parse.GeoPoint(10, 10);
|
||||||
|
const outbound = new Parse.GeoPoint(20, 20);
|
||||||
|
const obj1 = new Parse.Object('Polygon', {location: inbound});
|
||||||
|
const obj2 = new Parse.Object('Polygon', {location: onbound});
|
||||||
|
const obj3 = new Parse.Object('Polygon', {location: outbound});
|
||||||
|
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
|
||||||
|
const where = {
|
||||||
|
location: {
|
||||||
|
$geoWithin: {
|
||||||
|
$polygon: [
|
||||||
|
{ __type: 'GeoPoint', latitude: 0, longitude: 0 },
|
||||||
|
{ __type: 'GeoPoint', latitude: 0, longitude: 10 },
|
||||||
|
{ __type: 'GeoPoint', latitude: 10, longitude: 10 },
|
||||||
|
{ __type: 'GeoPoint', latitude: 10, longitude: 0 },
|
||||||
|
{ __type: 'GeoPoint', latitude: 0, longitude: 0 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return rp.post({
|
||||||
|
url: Parse.serverURL + '/classes/Polygon',
|
||||||
|
json: { where, '_method': 'GET' },
|
||||||
|
headers: {
|
||||||
|
'X-Parse-Application-Id': Parse.applicationId,
|
||||||
|
'X-Parse-Javascript-Key': Parse.javaScriptKey
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).then((resp) => {
|
||||||
|
expect(resp.results.length).toBe(2);
|
||||||
|
done();
|
||||||
|
}, done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
it('invalid input withinPolygon', (done) => {
|
it('invalid input withinPolygon', (done) => {
|
||||||
const point = new Parse.GeoPoint(1.5, 1.5);
|
const point = new Parse.GeoPoint(1.5, 1.5);
|
||||||
const obj = new Parse.Object('Polygon', {location: point});
|
const obj = new Parse.Object('Polygon', {location: point});
|
||||||
@@ -508,7 +546,8 @@ describe('Parse.GeoPoint testing', () => {
|
|||||||
$geoWithin: {
|
$geoWithin: {
|
||||||
$polygon: [
|
$polygon: [
|
||||||
{ __type: 'GeoPoint', latitude: 0, longitude: 0 },
|
{ __type: 'GeoPoint', latitude: 0, longitude: 0 },
|
||||||
{ __type: 'GeoPoint', latitude: 181, longitude: 0 }
|
{ __type: 'GeoPoint', latitude: 181, longitude: 0 },
|
||||||
|
{ __type: 'GeoPoint', latitude: 0, longitude: 0 }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -539,7 +578,8 @@ describe('Parse.GeoPoint testing', () => {
|
|||||||
$geoWithin: {
|
$geoWithin: {
|
||||||
$polygon: [
|
$polygon: [
|
||||||
{ __type: 'GeoPoint', latitude: 0, longitude: 0 },
|
{ __type: 'GeoPoint', latitude: 0, longitude: 0 },
|
||||||
{ __type: 'GeoPoint', latitude: 0, longitude: 181 }
|
{ __type: 'GeoPoint', latitude: 0, longitude: 181 },
|
||||||
|
{ __type: 'GeoPoint', latitude: 0, longitude: 0 }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -560,4 +600,32 @@ describe('Parse.GeoPoint testing', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('minimum 3 points withinPolygon', (done) => {
|
||||||
|
const point = new Parse.GeoPoint(1.5, 1.5);
|
||||||
|
const obj = new Parse.Object('Polygon', {location: point});
|
||||||
|
obj.save().then(() => {
|
||||||
|
const where = {
|
||||||
|
location: {
|
||||||
|
$geoWithin: {
|
||||||
|
$polygon: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return rp.post({
|
||||||
|
url: Parse.serverURL + '/classes/Polygon',
|
||||||
|
json: { where, '_method': 'GET' },
|
||||||
|
headers: {
|
||||||
|
'X-Parse-Application-Id': Parse.applicationId,
|
||||||
|
'X-Parse-Javascript-Key': Parse.javaScriptKey
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).then((resp) => {
|
||||||
|
fail(`no request should succeed: ${JSON.stringify(resp)}`);
|
||||||
|
done();
|
||||||
|
}).catch((err) => {
|
||||||
|
expect(err.error.code).toEqual(107);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -621,7 +621,16 @@ function transformConstraint(constraint, inArray) {
|
|||||||
case '$geoWithin': {
|
case '$geoWithin': {
|
||||||
const polygon = constraint[key]['$polygon'];
|
const polygon = constraint[key]['$polygon'];
|
||||||
if (!(polygon instanceof Array)) {
|
if (!(polygon instanceof Array)) {
|
||||||
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value');
|
throw new Parse.Error(
|
||||||
|
Parse.Error.INVALID_JSON,
|
||||||
|
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (polygon.length < 3) {
|
||||||
|
throw new Parse.Error(
|
||||||
|
Parse.Error.INVALID_JSON,
|
||||||
|
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const points = polygon.map((point) => {
|
const points = polygon.map((point) => {
|
||||||
if (!GeoPointCoder.isValidJSON(point)) {
|
if (!GeoPointCoder.isValidJSON(point)) {
|
||||||
|
|||||||
@@ -348,7 +348,16 @@ const buildWhereClause = ({ schema, query, index }) => {
|
|||||||
if (fieldValue.$geoWithin && fieldValue.$geoWithin.$polygon) {
|
if (fieldValue.$geoWithin && fieldValue.$geoWithin.$polygon) {
|
||||||
const polygon = fieldValue.$geoWithin.$polygon;
|
const polygon = fieldValue.$geoWithin.$polygon;
|
||||||
if (!(polygon instanceof Array)) {
|
if (!(polygon instanceof Array)) {
|
||||||
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value');
|
throw new Parse.Error(
|
||||||
|
Parse.Error.INVALID_JSON,
|
||||||
|
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (polygon.length < 3) {
|
||||||
|
throw new Parse.Error(
|
||||||
|
Parse.Error.INVALID_JSON,
|
||||||
|
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const points = polygon.map((point) => {
|
const points = polygon.map((point) => {
|
||||||
if (typeof point !== 'object' || point.__type !== 'GeoPoint') {
|
if (typeof point !== 'object' || point.__type !== 'GeoPoint') {
|
||||||
|
|||||||
Reference in New Issue
Block a user