Aggregate allow multiple of same stage (#4835)

* Aggregate Allow Multiple Stages

* remove testing files

* nit

* spread them
This commit is contained in:
Diamond Lewis
2018-06-23 11:28:17 -05:00
committed by Florent Vilmart
parent 197190fc29
commit df01846361
2 changed files with 106 additions and 41 deletions

View File

@@ -4,60 +4,56 @@ import * as middleware from '../middlewares';
import Parse from 'parse/node';
import UsersRouter from './UsersRouter';
const ALLOWED_KEYS = [
'where',
'distinct',
'project',
'match',
'redact',
'limit',
'skip',
'unwind',
'group',
'sample',
'sort',
'geoNear',
'lookup',
'out',
'indexStats',
'facet',
const BASE_KEYS = ['where', 'distinct'];
const PIPELINE_KEYS = [
'addFields',
'bucket',
'bucketAuto',
'sortByCount',
'addFields',
'replaceRoot',
'collStats',
'count',
'currentOp',
'facet',
'geoNear',
'graphLookup',
'group',
'indexStats',
'limit',
'listLocalSessions',
'listSessions',
'lookup',
'match',
'out',
'project',
'redact',
'replaceRoot',
'sample',
'skip',
'sort',
'sortByCount',
'unwind',
];
const ALLOWED_KEYS = [...BASE_KEYS, ...PIPELINE_KEYS];
export class AggregateRouter extends ClassesRouter {
handleFind(req) {
const body = Object.assign(req.body, ClassesRouter.JSONFromQuery(req.query));
const options = {};
const pipeline = [];
let pipeline = [];
for (const key in body) {
if (ALLOWED_KEYS.indexOf(key) === -1) {
throw new Parse.Error(Parse.Error.INVALID_QUERY, `Invalid parameter for query: ${key}`);
if (Array.isArray(body)) {
pipeline = body.map((stage) => {
const stageName = Object.keys(stage)[0];
return this.transformStage(stageName, stage);
});
} else {
const stages = [];
for (const stageName in body) {
stages.push(this.transformStage(stageName, body));
}
if (key === 'group') {
if (body[key].hasOwnProperty('_id')) {
throw new Parse.Error(
Parse.Error.INVALID_QUERY,
`Invalid parameter for query: group. Please use objectId instead of _id`
);
}
if (!body[key].hasOwnProperty('objectId')) {
throw new Parse.Error(
Parse.Error.INVALID_QUERY,
`Invalid parameter for query: group. objectId is required`
);
}
body[key]._id = body[key].objectId;
delete body[key].objectId;
}
pipeline.push({ [`$${key}`]: body[key] });
pipeline = stages;
}
if (body.distinct) {
options.distinct = String(body.distinct);
@@ -76,6 +72,32 @@ export class AggregateRouter extends ClassesRouter {
});
}
transformStage(stageName, stage) {
if (ALLOWED_KEYS.indexOf(stageName) === -1) {
throw new Parse.Error(
Parse.Error.INVALID_QUERY,
`Invalid parameter for query: ${stageName}`
);
}
if (stageName === 'group') {
if (stage[stageName].hasOwnProperty('_id')) {
throw new Parse.Error(
Parse.Error.INVALID_QUERY,
`Invalid parameter for query: group. Please use objectId instead of _id`
);
}
if (!stage[stageName].hasOwnProperty('objectId')) {
throw new Parse.Error(
Parse.Error.INVALID_QUERY,
`Invalid parameter for query: group. objectId is required`
);
}
stage[stageName]._id = stage[stageName].objectId;
delete stage[stageName].objectId;
}
return { [`$${stageName}`]: stage[stageName] };
}
mountRoutes() {
this.route('GET','/aggregate/:className', middleware.promiseEnforceMasterKeyAccess, req => { return this.handleFind(req); });
}