Add Polygon Type To Schema / PolygonContain to Query (#3944)

* Added type polygon to schema

* refactoring and more tests

* fix tests

* update test and transform

* add support for polygonContains

* fix transform.mongoObjectToParseObject test

* add indexes for polygon

* index test

* postgres test fix

* remove invalid loop test

* add invalid loop test

* nit
This commit is contained in:
Diamond Lewis
2017-07-11 22:33:45 -05:00
committed by Florent Vilmart
parent 0571c6f95e
commit e6cc8204b3
9 changed files with 470 additions and 5 deletions

View File

@@ -495,6 +495,9 @@ function transformTopLevelAtom(atom) {
if (GeoPointCoder.isValidJSON(atom)) {
return GeoPointCoder.JSONToDatabase(atom);
}
if (PolygonCoder.isValidJSON(atom)) {
return PolygonCoder.JSONToDatabase(atom);
}
if (FileCoder.isValidJSON(atom)) {
return FileCoder.JSONToDatabase(atom);
}
@@ -692,6 +695,24 @@ function transformConstraint(constraint, inArray) {
};
break;
}
case '$geoIntersects': {
const point = constraint[key]['$point'];
if (!GeoPointCoder.isValidJSON(point)) {
throw new Parse.Error(
Parse.Error.INVALID_JSON,
'bad $geoIntersect value; $point should be GeoPoint'
);
} else {
Parse.GeoPoint._validate(point.latitude, point.longitude);
}
answer[key] = {
$geometry: {
type: 'Point',
coordinates: [point.longitude, point.latitude]
}
};
break;
}
default:
if (key.match(/^\$+/)) {
throw new Parse.Error(
@@ -940,6 +961,10 @@ const mongoObjectToParseObject = (className, mongoObject, schema) => {
restObject[key] = GeoPointCoder.databaseToJSON(value);
break;
}
if (schema.fields[key] && schema.fields[key].type === 'Polygon' && PolygonCoder.isValidDatabaseObject(value)) {
restObject[key] = PolygonCoder.databaseToJSON(value);
break;
}
if (schema.fields[key] && schema.fields[key].type === 'Bytes' && BytesCoder.isValidDatabaseObject(value)) {
restObject[key] = BytesCoder.databaseToJSON(value);
break;
@@ -1043,6 +1068,64 @@ var GeoPointCoder = {
}
};
var PolygonCoder = {
databaseToJSON(object) {
return {
__type: 'Polygon',
coordinates: object['coordinates'][0]
}
},
isValidDatabaseObject(object) {
const coords = object.coordinates[0];
if (object.type !== 'Polygon' || !(coords instanceof Array)) {
return false;
}
for (let i = 0; i < coords.length; i++) {
const point = coords[i];
if (!GeoPointCoder.isValidDatabaseObject(point)) {
return false;
}
Parse.GeoPoint._validate(parseFloat(point[1]), parseFloat(point[0]));
}
return true;
},
JSONToDatabase(json) {
const coords = json.coordinates;
if (coords[0][0] !== coords[coords.length - 1][0] ||
coords[0][1] !== coords[coords.length - 1][1]) {
coords.push(coords[0]);
}
const unique = coords.filter((item, index, ar) => {
let foundIndex = -1;
for (let i = 0; i < ar.length; i += 1) {
const pt = ar[i];
if (pt[0] === item[0] &&
pt[1] === item[1]) {
foundIndex = i;
break;
}
}
return foundIndex === index;
});
if (unique.length < 3) {
throw new Parse.Error(
Parse.Error.INTERNAL_SERVER_ERROR,
'GeoJSON: Loop must have at least 3 different vertices'
);
}
return { type: 'Polygon', coordinates: [coords] };
},
isValidJSON(value) {
return (typeof value === 'object' &&
value !== null &&
value.__type === 'Polygon'
);
}
};
var FileCoder = {
databaseToJSON(object) {
return {