Skip to content

Commit fa0c705

Browse files
committed
feat: Resolve server-level query.aggregationRaw* defaults with per-query override
1 parent 2f39a13 commit fa0c705

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

spec/ParseQuery.Aggregate.spec.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,4 +1714,63 @@ describe('Parse.Query Aggregate testing', () => {
17141714
expect(Object.prototype.hasOwnProperty.call(results[0], 'objectId')).toBe(false);
17151715
expect(Object.prototype.hasOwnProperty.call(results[0], 'createdAt')).toBe(false);
17161716
});
1717+
1718+
it_id('f01a0003-0001-0001-0001-000000000001')(it_exclude_dbs(['postgres']))('server-level rawValues default applies when per-query omits it', async () => {
1719+
await reconfigureServer({ query: { aggregationRawValues: true } });
1720+
const obj = new TestObject();
1721+
await obj.save();
1722+
const iso = new Date(obj.createdAt.getTime() + 1).toISOString();
1723+
const pipeline = [
1724+
{ $match: { objectId: obj.id, createdAt: { $lte: { $date: iso } } } },
1725+
{ $count: 'total' },
1726+
];
1727+
const query = new Parse.Query('TestObject');
1728+
// No rawValues in the per-query options — should inherit from the server default.
1729+
const results = await query.aggregate(pipeline, { useMasterKey: true });
1730+
expect(results.length).toBe(1);
1731+
expect(results[0].total).toBe(1);
1732+
});
1733+
1734+
it_id('f01a0003-0002-0002-0002-000000000002')(it_exclude_dbs(['postgres']))('per-query rawValues: false overrides server-level true', async () => {
1735+
await reconfigureServer({ query: { aggregationRawValues: true } });
1736+
const obj = new TestObject();
1737+
await obj.save();
1738+
const iso = new Date(obj.createdAt.getTime() + 1).toISOString();
1739+
// With server-level rawValues: true, EJSON `{ $date: iso }` would be converted to a BSON Date
1740+
// and the $match would succeed. Per-query rawValues: false overrides that, so `{ $date: iso }`
1741+
// is NOT deserialized as EJSON and the comparison fails — proving the override works.
1742+
const pipeline = [
1743+
{ $match: { objectId: obj.id, createdAt: { $lte: { $date: iso } } } },
1744+
{ $count: 'total' },
1745+
];
1746+
const query = new Parse.Query('TestObject');
1747+
const results = await query.aggregate(pipeline, {
1748+
rawValues: false,
1749+
useMasterKey: true,
1750+
});
1751+
// Under rawValues: false the `{ $date: iso }` is not EJSON-deserialized; comparison yields no match.
1752+
expect(results.length).toBe(0);
1753+
});
1754+
1755+
it_id('f01a0003-0003-0003-0003-000000000003')(it_exclude_dbs(['postgres']))('server-level rawFieldNames default applies when per-query omits it', async () => {
1756+
await reconfigureServer({
1757+
query: { aggregationRawValues: true, aggregationRawFieldNames: true },
1758+
});
1759+
const obj = new TestObject();
1760+
await obj.save();
1761+
const iso = new Date(obj.createdAt.getTime() + 1).toISOString();
1762+
const pipeline = [
1763+
{
1764+
$match: {
1765+
_id: obj.id,
1766+
_created_at: { $lte: { $date: iso } },
1767+
},
1768+
},
1769+
{ $count: 'total' },
1770+
];
1771+
const query = new Parse.Query('TestObject');
1772+
const results = await query.aggregate(pipeline, { useMasterKey: true });
1773+
expect(results.length).toBe(1);
1774+
expect(results[0].total).toBe(1);
1775+
});
17171776
});

src/Routers/AggregateRouter.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ export class AggregateRouter extends ClassesRouter {
3535
options.rawFieldNames = body.rawFieldNames;
3636
delete body.rawFieldNames;
3737
}
38+
const queryOptions = (req.config && req.config.query) || {};
39+
if (options.rawValues === undefined && typeof queryOptions.aggregationRawValues === 'boolean') {
40+
options.rawValues = queryOptions.aggregationRawValues;
41+
}
42+
if (
43+
options.rawFieldNames === undefined &&
44+
typeof queryOptions.aggregationRawFieldNames === 'boolean'
45+
) {
46+
options.rawFieldNames = queryOptions.aggregationRawFieldNames;
47+
}
3848
options.pipeline = AggregateRouter.getPipeline(body);
3949
if (typeof body.where === 'string') {
4050
try {

0 commit comments

Comments
 (0)