Adds withinPolygon support for Polygon object (#4067)
* Whitespace * Add Polygon type to $polygon query * Add tests Polygon object in $polygon query $geoIntersects queries * Refactor * Postgres support * More tests * Remove duplicate test * Missing semicolon * fix tests
This commit is contained in:
committed by
Florent Vilmart
parent
4dcbc4245b
commit
57da2def1d
@@ -496,6 +496,116 @@ describe('Parse.GeoPoint testing', () => {
|
|||||||
}, done.fail);
|
}, done.fail);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('supports withinPolygon Polygon object', (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});
|
||||||
|
const polygon = {
|
||||||
|
__type: 'Polygon',
|
||||||
|
coordinates: [
|
||||||
|
[0, 0],
|
||||||
|
[10, 0],
|
||||||
|
[10, 10],
|
||||||
|
[0, 10],
|
||||||
|
[0, 0]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
|
||||||
|
const where = {
|
||||||
|
location: {
|
||||||
|
$geoWithin: {
|
||||||
|
$polygon: 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) => {
|
||||||
|
expect(resp.results.length).toBe(2);
|
||||||
|
done();
|
||||||
|
}, done.fail);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invalid Polygon object withinPolygon', (done) => {
|
||||||
|
const point = new Parse.GeoPoint(1.5, 1.5);
|
||||||
|
const obj = new Parse.Object('Polygon', {location: point});
|
||||||
|
const polygon = {
|
||||||
|
__type: 'Polygon',
|
||||||
|
coordinates: [
|
||||||
|
[0, 0],
|
||||||
|
[10, 0],
|
||||||
|
]
|
||||||
|
}
|
||||||
|
obj.save().then(() => {
|
||||||
|
const where = {
|
||||||
|
location: {
|
||||||
|
$geoWithin: {
|
||||||
|
$polygon: 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(Parse.Error.INVALID_JSON);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('out of bounds Polygon object withinPolygon', (done) => {
|
||||||
|
const point = new Parse.GeoPoint(1.5, 1.5);
|
||||||
|
const obj = new Parse.Object('Polygon', {location: point});
|
||||||
|
const polygon = {
|
||||||
|
__type: 'Polygon',
|
||||||
|
coordinates: [
|
||||||
|
[0, 0],
|
||||||
|
[181, 0],
|
||||||
|
[0, 10]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
obj.save().then(() => {
|
||||||
|
const where = {
|
||||||
|
location: {
|
||||||
|
$geoWithin: {
|
||||||
|
$polygon: 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(1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
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});
|
||||||
|
|||||||
@@ -905,19 +905,34 @@ function transformConstraint(constraint, field) {
|
|||||||
|
|
||||||
case '$geoWithin': {
|
case '$geoWithin': {
|
||||||
const polygon = constraint[key]['$polygon'];
|
const polygon = constraint[key]['$polygon'];
|
||||||
if (!(polygon instanceof Array)) {
|
let points;
|
||||||
|
if (typeof polygon === 'object' && polygon.__type === 'Polygon') {
|
||||||
|
if (!polygon.coordinates || polygon.coordinates.length < 3) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INVALID_JSON,
|
Parse.Error.INVALID_JSON,
|
||||||
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
|
'bad $geoWithin value; Polygon.coordinates should contain at least 3 lon/lat pairs'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
points = polygon.coordinates;
|
||||||
|
} else if (polygon instanceof Array) {
|
||||||
if (polygon.length < 3) {
|
if (polygon.length < 3) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INVALID_JSON,
|
Parse.Error.INVALID_JSON,
|
||||||
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
|
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const points = polygon.map((point) => {
|
points = polygon;
|
||||||
|
} else {
|
||||||
|
throw new Parse.Error(
|
||||||
|
Parse.Error.INVALID_JSON,
|
||||||
|
'bad $geoWithin value; $polygon should be Polygon object or Array of Parse.GeoPoint\'s'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
points = points.map((point) => {
|
||||||
|
if (point instanceof Array && point.length === 2) {
|
||||||
|
Parse.GeoPoint._validate(point[1], point[0]);
|
||||||
|
return point;
|
||||||
|
}
|
||||||
if (!GeoPointCoder.isValidJSON(point)) {
|
if (!GeoPointCoder.isValidJSON(point)) {
|
||||||
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value');
|
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value');
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -537,19 +537,34 @@ const buildWhereClause = ({ schema, query, index }): WhereClause => {
|
|||||||
|
|
||||||
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)) {
|
let points;
|
||||||
|
if (typeof polygon === 'object' && polygon.__type === 'Polygon') {
|
||||||
|
if (!polygon.coordinates || polygon.coordinates.length < 3) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INVALID_JSON,
|
Parse.Error.INVALID_JSON,
|
||||||
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
|
'bad $geoWithin value; Polygon.coordinates should contain at least 3 lon/lat pairs'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
points = polygon.coordinates;
|
||||||
|
} else if ((polygon instanceof Array)) {
|
||||||
if (polygon.length < 3) {
|
if (polygon.length < 3) {
|
||||||
throw new Parse.Error(
|
throw new Parse.Error(
|
||||||
Parse.Error.INVALID_JSON,
|
Parse.Error.INVALID_JSON,
|
||||||
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
|
'bad $geoWithin value; $polygon should contain at least 3 GeoPoints'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const points = polygon.map((point) => {
|
points = polygon;
|
||||||
|
} else {
|
||||||
|
throw new Parse.Error(
|
||||||
|
Parse.Error.INVALID_JSON,
|
||||||
|
'bad $geoWithin value; $polygon should be Polygon object or Array of Parse.GeoPoint\'s'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
points = points.map((point) => {
|
||||||
|
if (point instanceof Array && point.length === 2) {
|
||||||
|
Parse.GeoPoint._validate(point[1], point[0]);
|
||||||
|
return `(${point[0]}, ${point[1]})`;
|
||||||
|
}
|
||||||
if (typeof point !== 'object' || point.__type !== 'GeoPoint') {
|
if (typeof point !== 'object' || point.__type !== 'GeoPoint') {
|
||||||
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value');
|
throw new Parse.Error(Parse.Error.INVALID_JSON, 'bad $geoWithin value');
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user