Move query logic into mongo (#1885)

* Move Parse Server logic into Parse Server and out of MongoAdapter

* Move untransforming up one level

* Make find() in MongoStorageAdapter

* Put nested object untransforming into it's own function

* Simplfy nested untransform

* Don't mess with inner object keys called _auth_data_*

* Prevent untransforming inner object keys named _p_*

* Fix inner keys named _rperm, _wperm

* Fix bugs with inner objects behaving strange when other fields have same name as key in specific circumstances

* remove params from untransform nested object

* Revert changes to find
This commit is contained in:
Drew
2016-05-23 16:31:51 -07:00
committed by Florent Vilmart
parent 88fa7bad92
commit 614e1ac8e5
6 changed files with 184 additions and 124 deletions

View File

@@ -197,6 +197,14 @@ export class MongoStorageAdapter {
});
}
// Executes a find. Accepts: className, query in Parse format, and { skip, limit, sort }.
// Accepts the schemaController for legacy reasons.
find(className, query, { skip, limit, sort }, schemaController) {
return this.adaptiveCollection(className)
.then(collection => collection.find(query, { skip, limit, sort }))
.then(objects => objects.map(object => transform.mongoObjectToParseObject(schemaController, className, object)));
}
get transform() {
return transform;
}

View File

@@ -713,25 +713,7 @@ function transformUpdateOperator({
}
}
const specialKeysForUntransform = [
'_id',
'_hashed_password',
'_acl',
'_email_verify_token',
'_perishable_token',
'_tombstone',
'_session_token',
'updatedAt',
'_updated_at',
'createdAt',
'_created_at',
'expiresAt',
'_expiresAt',
];
// Converts from a mongo-format object to a REST-format object.
// Does not strip out anything based on a lack of authentication.
function untransformObject(schema, className, mongoObject, isNestedObject = false) {
const nestedMongoObjectToNestedParseObject = mongoObject => {
switch(typeof mongoObject) {
case 'string':
case 'number':
@@ -740,15 +722,55 @@ function untransformObject(schema, className, mongoObject, isNestedObject = fals
case 'undefined':
case 'symbol':
case 'function':
throw 'bad value in untransformObject';
throw 'bad value in mongoObjectToParseObject';
case 'object':
if (mongoObject === null) {
return null;
}
if (mongoObject instanceof Array) {
return mongoObject.map(arrayEntry => {
return untransformObject(schema, className, arrayEntry, true);
});
return mongoObject.map(nestedMongoObjectToNestedParseObject);
}
if (mongoObject instanceof Date) {
return Parse._encode(mongoObject);
}
if (mongoObject instanceof mongodb.Long) {
return mongoObject.toNumber();
}
if (mongoObject instanceof mongodb.Double) {
return mongoObject.value;
}
if (BytesCoder.isValidDatabaseObject(mongoObject)) {
return BytesCoder.databaseToJSON(mongoObject);
}
return _.mapValues(mongoObject, nestedMongoObjectToNestedParseObject);
default:
throw 'unknown js type';
}
}
// Converts from a mongo-format object to a REST-format object.
// Does not strip out anything based on a lack of authentication.
const mongoObjectToParseObject = (schema, className, mongoObject) => {
switch(typeof mongoObject) {
case 'string':
case 'number':
case 'boolean':
return mongoObject;
case 'undefined':
case 'symbol':
case 'function':
throw 'bad value in mongoObjectToParseObject';
case 'object':
if (mongoObject === null) {
return null;
}
if (mongoObject instanceof Array) {
return mongoObject.map(nestedMongoObjectToNestedParseObject);
}
if (mongoObject instanceof Date) {
@@ -769,10 +791,6 @@ function untransformObject(schema, className, mongoObject, isNestedObject = fals
var restObject = untransformACL(mongoObject);
for (var key in mongoObject) {
if (isNestedObject && _.includes(specialKeysForUntransform, key)) {
restObject[key] = untransformObject(schema, className, mongoObject[key], true);
continue;
}
switch(key) {
case '_id':
restObject['objectId'] = '' + mongoObject[key];
@@ -840,7 +858,7 @@ function untransformObject(schema, className, mongoObject, isNestedObject = fals
objectId: objData[1]
};
break;
} else if (!isNestedObject && key[0] == '_' && key != '__type') {
} else if (key[0] == '_' && key != '__type') {
throw ('bad key in untransform: ' + key);
} else {
var expectedType = schema.getExpectedType(className, key);
@@ -854,80 +872,16 @@ function untransformObject(schema, className, mongoObject, isNestedObject = fals
break;
}
}
restObject[key] = untransformObject(schema, className, mongoObject[key], true);
restObject[key] = nestedMongoObjectToNestedParseObject(mongoObject[key]);
}
}
if (!isNestedObject) {
let relationFields = schema.getRelationFields(className);
Object.assign(restObject, relationFields);
}
return restObject;
return { ...restObject, ...schema.getRelationFields(className) };
default:
throw 'unknown js type';
}
}
function transformSelect(selectObject, key ,objects) {
var values = [];
for (var result of objects) {
values.push(result[key]);
}
delete selectObject['$select'];
if (Array.isArray(selectObject['$in'])) {
selectObject['$in'] = selectObject['$in'].concat(values);
} else {
selectObject['$in'] = values;
}
}
function transformDontSelect(dontSelectObject, key, objects) {
var values = [];
for (var result of objects) {
values.push(result[key]);
}
delete dontSelectObject['$dontSelect'];
if (Array.isArray(dontSelectObject['$nin'])) {
dontSelectObject['$nin'] = dontSelectObject['$nin'].concat(values);
} else {
dontSelectObject['$nin'] = values;
}
}
function transformInQuery(inQueryObject, className, results) {
var values = [];
for (var result of results) {
values.push({
__type: 'Pointer',
className: className,
objectId: result.objectId
});
}
delete inQueryObject['$inQuery'];
if (Array.isArray(inQueryObject['$in'])) {
inQueryObject['$in'] = inQueryObject['$in'].concat(values);
} else {
inQueryObject['$in'] = values;
}
}
function transformNotInQuery(notInQueryObject, className, results) {
var values = [];
for (var result of results) {
values.push({
__type: 'Pointer',
className: className,
objectId: result.objectId
});
}
delete notInQueryObject['$notInQuery'];
if (Array.isArray(notInQueryObject['$nin'])) {
notInQueryObject['$nin'] = notInQueryObject['$nin'].concat(values);
} else {
notInQueryObject['$nin'] = values;
}
}
var DateCoder = {
JSONToDatabase(json) {
return new Date(json.iso);
@@ -1021,9 +975,5 @@ module.exports = {
parseObjectToMongoObjectForCreate,
transformUpdate,
transformWhere,
transformSelect,
transformDontSelect,
transformInQuery,
transformNotInQuery,
untransformObject
mongoObjectToParseObject,
};