#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
This commit is contained in:
Chris
2018-06-26 18:18:04 -04:00
committed by Diamond Lewis
parent 3ace26da6f
commit 5cdbde244a
2 changed files with 380 additions and 16 deletions

View File

@@ -164,6 +164,124 @@ describe('Parse.Query Aggregate testing', () => {
});
});
it('group by date object transform', (done) => {
const obj1 = new TestObject();
const obj2 = new TestObject();
const obj3 = new TestObject();
const pipeline = [{
group: {
objectId: { day: { $dayOfMonth: "$updatedAt" }, month: { $month: "$createdAt" }, year: { $year: "$createdAt" } },
count: { $sum: 1 }
}
}];
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
const query = new Parse.Query(TestObject);
return query.aggregate(pipeline);
}).then((results) => {
const createdAt = new Date(obj1.createdAt);
expect(results[0].objectId.day).toEqual(createdAt.getUTCDate());
expect(results[0].objectId.month).toEqual(createdAt.getMonth() + 1);
expect(results[0].objectId.year).toEqual(createdAt.getUTCFullYear());
done();
});
});
it_exclude_dbs(['postgres'])('group and multiply transform', (done) => {
const obj1 = new TestObject({ name: 'item a', quantity: 2, price: 10 });
const obj2 = new TestObject({ name: 'item b', quantity: 5, price: 5 });
const pipeline = [{
group: {
objectId: null,
total: { $sum: { $multiply: [ '$quantity', '$price' ] } }
}
}];
Parse.Object.saveAll([obj1, obj2]).then(() => {
const query = new Parse.Query(TestObject);
return query.aggregate(pipeline);
}).then((results) => {
expect(results.length).toEqual(1);
expect(results[0].total).toEqual(45);
done();
});
});
it_exclude_dbs(['postgres'])('project and multiply transform', (done) => {
const obj1 = new TestObject({ name: 'item a', quantity: 2, price: 10 });
const obj2 = new TestObject({ name: 'item b', quantity: 5, price: 5 });
const pipeline = [
{
match: { quantity: { $exists: true } }
},
{
project: {
name: 1,
total: { $multiply: [ '$quantity', '$price' ] }
}
}
];
Parse.Object.saveAll([obj1, obj2]).then(() => {
const query = new Parse.Query(TestObject);
return query.aggregate(pipeline);
}).then((results) => {
expect(results.length).toEqual(2);
if (results[0].name === 'item a') {
expect(results[0].total).toEqual(20);
expect(results[1].total).toEqual(25);
}
else {
expect(results[0].total).toEqual(25);
expect(results[1].total).toEqual(20);
}
done();
});
});
it_exclude_dbs(['postgres'])('project without objectId transform', (done) => {
const obj1 = new TestObject({ name: 'item a', quantity: 2, price: 10 });
const obj2 = new TestObject({ name: 'item b', quantity: 5, price: 5 });
const pipeline = [
{
match: { quantity: { $exists: true } }
},
{
project: {
objectId: 0,
total: { $multiply: [ '$quantity', '$price' ] }
}
},
{
sort: { total: 1 }
}
];
Parse.Object.saveAll([obj1, obj2]).then(() => {
const query = new Parse.Query(TestObject);
return query.aggregate(pipeline);
}).then((results) => {
expect(results.length).toEqual(2);
expect(results[0].total).toEqual(20);
expect(results[0].objectId).toEqual(undefined);
expect(results[1].total).toEqual(25);
expect(results[1].objectId).toEqual(undefined);
done();
});
});
it_exclude_dbs(['postgres'])('project updatedAt only transform', (done) => {
const pipeline = [{
project: { objectId: 0, updatedAt: 1 }
}];
const query = new Parse.Query(TestObject);
query.aggregate(pipeline).then((results) => {
expect(results.length).toEqual(4);
for (let i = 0; i < results.length; i++) {
const item = results[i];
expect(item.hasOwnProperty('updatedAt')).toEqual(true);
expect(item.hasOwnProperty('objectId')).toEqual(false);
}
done();
});
});
it_exclude_dbs(['postgres'])('cannot group by date field (excluding createdAt and updatedAt)', (done) => {
const obj1 = new TestObject({ dateField: new Date(1990, 11, 1) });
const obj2 = new TestObject({ dateField: new Date(1990, 5, 1) });
@@ -339,6 +457,27 @@ describe('Parse.Query Aggregate testing', () => {
}).catch(done.fail);
});
it('match comparison date query', (done) => {
const today = new Date();
const yesterday = new Date();
const tomorrow = new Date();
yesterday.setDate(today.getDate() - 1);
tomorrow.setDate(today.getDate() + 1);
const obj1 = new TestObject({ dateField: yesterday });
const obj2 = new TestObject({ dateField: today });
const obj3 = new TestObject({ dateField: tomorrow });
const pipeline = [
{ match: { dateField: { $lt: tomorrow } } }
];
Parse.Object.saveAll([obj1, obj2, obj3]).then(() => {
const query = new Parse.Query(TestObject);
return query.aggregate(pipeline);
}).then((results) => {
expect(results.length).toBe(2);
done();
});
});
it('match comparison query', (done) => {
const options = Object.assign({}, masterKeyOptions, {
body: {
@@ -474,6 +613,96 @@ describe('Parse.Query Aggregate testing', () => {
});
});
it_exclude_dbs(['postgres'])('match exists query', (done) => {
const pipeline = [
{ match: { score: { $exists: true } } }
];
const query = new Parse.Query(TestObject);
query.aggregate(pipeline).then((results) => {
expect(results.length).toEqual(4);
done();
});
});
it('match date query - createdAt', (done) => {
const obj1 = new TestObject();
const obj2 = new TestObject();
Parse.Object.saveAll([obj1, obj2]).then(() => {
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const pipeline = [
{ match: { 'createdAt': { $gte: today } } }
];
const query = new Parse.Query(TestObject);
return query.aggregate(pipeline);
}).then((results) => {
// Four objects were created initially, we added two more.
expect(results.length).toEqual(6);
done();
});
});
it('match date query - updatedAt', (done) => {
const obj1 = new TestObject();
const obj2 = new TestObject();
Parse.Object.saveAll([obj1, obj2]).then(() => {
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const pipeline = [
{ match: { 'updatedAt': { $gte: today } } }
];
const query = new Parse.Query(TestObject);
return query.aggregate(pipeline);
}).then((results) => {
// Four objects were added initially, we added two more.
expect(results.length).toEqual(6);
done();
});
});
it('match date query - empty', (done) => {
const obj1 = new TestObject();
const obj2 = new TestObject();
Parse.Object.saveAll([obj1, obj2]).then(() => {
const now = new Date();
const future = new Date(now.getFullYear(), now.getMonth() + 1, now.getDate());
const pipeline = [
{ match: { 'createdAt': future } }
];
const query = new Parse.Query(TestObject);
return query.aggregate(pipeline);
}).then((results) => {
expect(results.length).toEqual(0);
done();
});
});
it_exclude_dbs(['postgres'])('match pointer with operator query', (done) => {
const pointer = new PointerObject();
const obj1 = new TestObject({ pointer });
const obj2 = new TestObject({ pointer });
const obj3 = new TestObject();
Parse.Object.saveAll([pointer, obj1, obj2, obj3]).then(() => {
const pipeline = [
{ match: { pointer: { $exists: true } } }
];
const query = new Parse.Query(TestObject);
return query.aggregate(pipeline);
}).then((results) => {
expect(results.length).toEqual(2);
expect(results[0].pointer.objectId).toEqual(pointer.id);
expect(results[1].pointer.objectId).toEqual(pointer.id);
expect(results.some(result => result.objectId === obj1.id)).toEqual(true);
expect(results.some(result => result.objectId === obj2.id)).toEqual(true);
done();
});
});
it('project query', (done) => {
const options = Object.assign({}, masterKeyOptions, {
body: {
@@ -512,6 +741,26 @@ describe('Parse.Query Aggregate testing', () => {
}).catch(done.fail);
});
it('project pointer query', (done) => {
const pointer = new PointerObject();
const obj = new TestObject({ pointer, name: 'hello' });
obj.save().then(() => {
const pipeline = [
{ match: { objectId: obj.id } },
{ project: { pointer: 1, name: 1, createdAt: 1 } }
];
const query = new Parse.Query(TestObject);
return query.aggregate(pipeline);
}).then((results) => {
expect(results.length).toEqual(1);
expect(results[0].name).toEqual('hello');
expect(results[0].createdAt).not.toBe(undefined);
expect(results[0].pointer.objectId).toEqual(pointer.id);
done();
});
});
it('project with group query', (done) => {
const options = Object.assign({}, masterKeyOptions, {
body: {