Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ ___
- Add REST API endpoint `/loginAs` to create session of any user with master key; allows to impersonate another user. (GormanFletcher) [#7406](https://github.com/parse-community/parse-server/pull/7406)

### Other Changes
- Support aggregation stage names starting with `$` and `$group` stages using `_id` instead of `objectId`, just like in MongoDB (Raschid JF Rafeally) [#7339](https://github.com/parse-community/parse-server/pull/7339)
- Fix error when a not yet inserted job is updated (Antonio Davi Macedo Coelho de Castro) [#7196](https://github.com/parse-community/parse-server/pull/7196)
- request.context for afterFind triggers (dblythy) [#7078](https://github.com/parse-community/parse-server/pull/7078)
- Winston Logger interpolating stdout to console (dplewis) [#7114](https://github.com/parse-community/parse-server/pull/7114)
Expand Down
18 changes: 18 additions & 0 deletions spec/AggregateRouter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,22 @@ describe('AggregateRouter', () => {
const result = AggregateRouter.getPipeline(body);
expect(result).toEqual(expected);
});

it("support stage name starting with '$'", () => {
const body = {
$match: { someKey: 'whatever' },
};
const expected = [{ $match: { someKey: 'whatever' } }];
const result = AggregateRouter.getPipeline(body);
expect(result).toEqual(expected);
});

it("support group stage using '_id'", () => {
const body = {
group: { _id: {} },
};
const expected = [{ $group: { _id: {} } }];
const result = AggregateRouter.getPipeline(body);
expect(result).toEqual(expected);
});
});
29 changes: 19 additions & 10 deletions src/Routers/AggregateRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import rest from '../rest';
import * as middleware from '../middlewares';
import Parse from 'parse/node';
import UsersRouter from './UsersRouter';
import Deprecator from '../Deprecator/Deprecator';

export class AggregateRouter extends ClassesRouter {
handleFind(req) {
Expand Down Expand Up @@ -91,22 +92,30 @@ export class AggregateRouter extends ClassesRouter {

static transformStage(stageName, stage) {
if (stageName === 'group') {
if (Object.prototype.hasOwnProperty.call(stage[stageName], '_id')) {
throw new Parse.Error(
Parse.Error.INVALID_QUERY,
`Invalid parameter for query: group. Please use objectId instead of _id`
);
if (Object.prototype.hasOwnProperty.call(stage[stageName], 'objectId')) {
Deprecator.logRuntimeDeprecation({
usage: 'The use of objectId in aggregation stage $group',
solution: 'Use _id instead.',
});
stage[stageName]._id = stage[stageName].objectId;
delete stage[stageName].objectId;
}
if (!Object.prototype.hasOwnProperty.call(stage[stageName], 'objectId')) {
if (!Object.prototype.hasOwnProperty.call(stage[stageName], '_id')) {
throw new Parse.Error(
Parse.Error.INVALID_QUERY,
`Invalid parameter for query: group. objectId is required`
`Invalid parameter for query: group. Missing key _id`
);
}
stage[stageName]._id = stage[stageName].objectId;
delete stage[stageName].objectId;
}
return { [`$${stageName}`]: stage[stageName] };

if (stageName[0] !== '$') {
Deprecator.logRuntimeDeprecation({
usage: "Using aggregation stages without a leading '$'",
solution: `Try $${stageName} instead.`,
});
}
const key = stageName[0] === '$' ? stageName : `$${stageName}`;
return { [key]: stage[stageName] };
}

mountRoutes() {
Expand Down