Skip to content

Commit 5cdbde2

Browse files
cjblanddplewis
authored andcommitted
#4678: Converting strings to Date when schema.type is Date within agg… (#4743)
* #4678: Converting strings to Date when schema.type is Date within aggregate function * Added test cases to test new date match aggregate query * Added function to parse match aggregate arguments and convert necessary values to Date objects * Added missing return value * Improved code quality based on suggestions and figured out why tests were failing * Added tests from @dplewis * Supporting project aggregation as well as exists operator * Excluding exists match for postgres * Handling the $group operator similar to $match and $project * Added more tests for better code coverage * Excluding certain tests from being run on postgres * Excluding one more test from postgres * clean up
1 parent 3ace26d commit 5cdbde2

File tree

2 files changed

+380
-16
lines changed

2 files changed

+380
-16
lines changed

spec/ParseQuery.Aggregate.spec.js

+249
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,124 @@ describe('Parse.Query Aggregate testing', () => {
164164
});
165165
});
166166

167+
it('group by date object transform', (done) => {
168+
const obj1 = new TestObject();
169+
const obj2 = new TestObject();
170+
const obj3 = new TestObject();
171+
const pipeline = [{
172+
group: {
173+
objectId: { day: { $dayOfMonth: "$updatedAt" }, month: { $month: "$createdAt" }, year: { $year: "$createdAt" } },
174+
count: { $sum: 1 }
175+
}
176+
}];
177+
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
178+
const query = new Parse.Query(TestObject);
179+
return query.aggregate(pipeline);
180+
}).then((results) => {
181+
const createdAt = new Date(obj1.createdAt);
182+
expect(results[0].objectId.day).toEqual(createdAt.getUTCDate());
183+
expect(results[0].objectId.month).toEqual(createdAt.getMonth() + 1);
184+
expect(results[0].objectId.year).toEqual(createdAt.getUTCFullYear());
185+
done();
186+
});
187+
});
188+
189+
it_exclude_dbs(['postgres'])('group and multiply transform', (done) => {
190+
const obj1 = new TestObject({ name: 'item a', quantity: 2, price: 10 });
191+
const obj2 = new TestObject({ name: 'item b', quantity: 5, price: 5 });
192+
const pipeline = [{
193+
group: {
194+
objectId: null,
195+
total: { $sum: { $multiply: [ '$quantity', '$price' ] } }
196+
}
197+
}];
198+
Parse.Object.saveAll([obj1, obj2]).then(() => {
199+
const query = new Parse.Query(TestObject);
200+
return query.aggregate(pipeline);
201+
}).then((results) => {
202+
expect(results.length).toEqual(1);
203+
expect(results[0].total).toEqual(45);
204+
done();
205+
});
206+
});
207+
208+
it_exclude_dbs(['postgres'])('project and multiply transform', (done) => {
209+
const obj1 = new TestObject({ name: 'item a', quantity: 2, price: 10 });
210+
const obj2 = new TestObject({ name: 'item b', quantity: 5, price: 5 });
211+
const pipeline = [
212+
{
213+
match: { quantity: { $exists: true } }
214+
},
215+
{
216+
project: {
217+
name: 1,
218+
total: { $multiply: [ '$quantity', '$price' ] }
219+
}
220+
}
221+
];
222+
Parse.Object.saveAll([obj1, obj2]).then(() => {
223+
const query = new Parse.Query(TestObject);
224+
return query.aggregate(pipeline);
225+
}).then((results) => {
226+
expect(results.length).toEqual(2);
227+
if (results[0].name === 'item a') {
228+
expect(results[0].total).toEqual(20);
229+
expect(results[1].total).toEqual(25);
230+
}
231+
else {
232+
expect(results[0].total).toEqual(25);
233+
expect(results[1].total).toEqual(20);
234+
}
235+
done();
236+
});
237+
});
238+
239+
it_exclude_dbs(['postgres'])('project without objectId transform', (done) => {
240+
const obj1 = new TestObject({ name: 'item a', quantity: 2, price: 10 });
241+
const obj2 = new TestObject({ name: 'item b', quantity: 5, price: 5 });
242+
const pipeline = [
243+
{
244+
match: { quantity: { $exists: true } }
245+
},
246+
{
247+
project: {
248+
objectId: 0,
249+
total: { $multiply: [ '$quantity', '$price' ] }
250+
}
251+
},
252+
{
253+
sort: { total: 1 }
254+
}
255+
];
256+
Parse.Object.saveAll([obj1, obj2]).then(() => {
257+
const query = new Parse.Query(TestObject);
258+
return query.aggregate(pipeline);
259+
}).then((results) => {
260+
expect(results.length).toEqual(2);
261+
expect(results[0].total).toEqual(20);
262+
expect(results[0].objectId).toEqual(undefined);
263+
expect(results[1].total).toEqual(25);
264+
expect(results[1].objectId).toEqual(undefined);
265+
done();
266+
});
267+
});
268+
269+
it_exclude_dbs(['postgres'])('project updatedAt only transform', (done) => {
270+
const pipeline = [{
271+
project: { objectId: 0, updatedAt: 1 }
272+
}];
273+
const query = new Parse.Query(TestObject);
274+
query.aggregate(pipeline).then((results) => {
275+
expect(results.length).toEqual(4);
276+
for (let i = 0; i < results.length; i++) {
277+
const item = results[i];
278+
expect(item.hasOwnProperty('updatedAt')).toEqual(true);
279+
expect(item.hasOwnProperty('objectId')).toEqual(false);
280+
}
281+
done();
282+
});
283+
});
284+
167285
it_exclude_dbs(['postgres'])('cannot group by date field (excluding createdAt and updatedAt)', (done) => {
168286
const obj1 = new TestObject({ dateField: new Date(1990, 11, 1) });
169287
const obj2 = new TestObject({ dateField: new Date(1990, 5, 1) });
@@ -339,6 +457,27 @@ describe('Parse.Query Aggregate testing', () => {
339457
}).catch(done.fail);
340458
});
341459

460+
it('match comparison date query', (done) => {
461+
const today = new Date();
462+
const yesterday = new Date();
463+
const tomorrow = new Date();
464+
yesterday.setDate(today.getDate() - 1);
465+
tomorrow.setDate(today.getDate() + 1);
466+
const obj1 = new TestObject({ dateField: yesterday });
467+
const obj2 = new TestObject({ dateField: today });
468+
const obj3 = new TestObject({ dateField: tomorrow });
469+
const pipeline = [
470+
{ match: { dateField: { $lt: tomorrow } } }
471+
];
472+
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
473+
const query = new Parse.Query(TestObject);
474+
return query.aggregate(pipeline);
475+
}).then((results) => {
476+
expect(results.length).toBe(2);
477+
done();
478+
});
479+
});
480+
342481
it('match comparison query', (done) => {
343482
const options = Object.assign({}, masterKeyOptions, {
344483
body: {
@@ -474,6 +613,96 @@ describe('Parse.Query Aggregate testing', () => {
474613
});
475614
});
476615

616+
it_exclude_dbs(['postgres'])('match exists query', (done) => {
617+
const pipeline = [
618+
{ match: { score: { $exists: true } } }
619+
];
620+
const query = new Parse.Query(TestObject);
621+
query.aggregate(pipeline).then((results) => {
622+
expect(results.length).toEqual(4);
623+
done();
624+
});
625+
});
626+
627+
it('match date query - createdAt', (done) => {
628+
const obj1 = new TestObject();
629+
const obj2 = new TestObject();
630+
631+
Parse.Object.saveAll([obj1, obj2]).then(() => {
632+
const now = new Date();
633+
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
634+
const pipeline = [
635+
{ match: { 'createdAt': { $gte: today } } }
636+
];
637+
const query = new Parse.Query(TestObject);
638+
return query.aggregate(pipeline);
639+
}).then((results) => {
640+
// Four objects were created initially, we added two more.
641+
expect(results.length).toEqual(6);
642+
done();
643+
});
644+
});
645+
646+
it('match date query - updatedAt', (done) => {
647+
const obj1 = new TestObject();
648+
const obj2 = new TestObject();
649+
650+
Parse.Object.saveAll([obj1, obj2]).then(() => {
651+
const now = new Date();
652+
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
653+
const pipeline = [
654+
{ match: { 'updatedAt': { $gte: today } } }
655+
];
656+
const query = new Parse.Query(TestObject);
657+
return query.aggregate(pipeline);
658+
}).then((results) => {
659+
// Four objects were added initially, we added two more.
660+
expect(results.length).toEqual(6);
661+
done();
662+
});
663+
});
664+
665+
it('match date query - empty', (done) => {
666+
const obj1 = new TestObject();
667+
const obj2 = new TestObject();
668+
669+
Parse.Object.saveAll([obj1, obj2]).then(() => {
670+
const now = new Date();
671+
const future = new Date(now.getFullYear(), now.getMonth() + 1, now.getDate());
672+
const pipeline = [
673+
{ match: { 'createdAt': future } }
674+
];
675+
const query = new Parse.Query(TestObject);
676+
return query.aggregate(pipeline);
677+
}).then((results) => {
678+
expect(results.length).toEqual(0);
679+
done();
680+
});
681+
});
682+
683+
it_exclude_dbs(['postgres'])('match pointer with operator query', (done) => {
684+
const pointer = new PointerObject();
685+
686+
const obj1 = new TestObject({ pointer });
687+
const obj2 = new TestObject({ pointer });
688+
const obj3 = new TestObject();
689+
690+
Parse.Object.saveAll([pointer, obj1, obj2, obj3]).then(() => {
691+
const pipeline = [
692+
{ match: { pointer: { $exists: true } } }
693+
];
694+
const query = new Parse.Query(TestObject);
695+
return query.aggregate(pipeline);
696+
}).then((results) => {
697+
expect(results.length).toEqual(2);
698+
expect(results[0].pointer.objectId).toEqual(pointer.id);
699+
expect(results[1].pointer.objectId).toEqual(pointer.id);
700+
expect(results.some(result => result.objectId === obj1.id)).toEqual(true);
701+
expect(results.some(result => result.objectId === obj2.id)).toEqual(true);
702+
done();
703+
});
704+
});
705+
477706
it('project query', (done) => {
478707
const options = Object.assign({}, masterKeyOptions, {
479708
body: {
@@ -512,6 +741,26 @@ describe('Parse.Query Aggregate testing', () => {
512741
}).catch(done.fail);
513742
});
514743

744+
it('project pointer query', (done) => {
745+
const pointer = new PointerObject();
746+
const obj = new TestObject({ pointer, name: 'hello' });
747+
748+
obj.save().then(() => {
749+
const pipeline = [
750+
{ match: { objectId: obj.id } },
751+
{ project: { pointer: 1, name: 1, createdAt: 1 } }
752+
];
753+
const query = new Parse.Query(TestObject);
754+
return query.aggregate(pipeline);
755+
}).then((results) => {
756+
expect(results.length).toEqual(1);
757+
expect(results[0].name).toEqual('hello');
758+
expect(results[0].createdAt).not.toBe(undefined);
759+
expect(results[0].pointer.objectId).toEqual(pointer.id);
760+
done();
761+
});
762+
});
763+
515764
it('project with group query', (done) => {
516765
const options = Object.assign({}, masterKeyOptions, {
517766
body: {

0 commit comments

Comments
 (0)