Skip to content

#4678: Converting strings to Date when schema.type is Date within agg… #4743

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Jun 26, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fa8c902
#4678: Converting strings to Date when schema.type is Date within agg…
cjbland Apr 30, 2018
9a12b7c
Added test cases to test new date match aggregate query
cjbland Apr 30, 2018
044453a
Added function to parse match aggregate arguments and convert necessa…
cjbland May 1, 2018
90b43ba
Merge branch 'master' into fix/4678
cjbland May 1, 2018
1714711
Added missing return value
cjbland May 2, 2018
867863e
Merge branch 'fix/4678' of https://github.com/cjbland/parse-server in…
cjbland May 2, 2018
d922a7a
Improved code quality based on suggestions and figured out why tests …
cjbland May 4, 2018
7261ba0
Added tests from @dplewis
cjbland May 19, 2018
beb54bb
Supporting project aggregation as well as exists operator
cjbland May 19, 2018
403e81b
Merge branch 'master' into fix/4678
cjbland May 19, 2018
9526c65
Merge branch 'master' into fix/4678
cjbland May 19, 2018
7993f45
Merge branch 'fix/4678' of https://github.com/cjbland/parse-server in…
cjbland May 19, 2018
f8c06d9
Merge branch 'master' into fix/4678
cjbland May 22, 2018
abf42d9
Excluding exists match for postgres
cjbland May 23, 2018
f7edfa5
Merge branch 'master' into fix/4678
cjbland Jun 16, 2018
cdc90e2
Merge branch 'master' into fix/4678
cjbland Jun 16, 2018
52b2f7f
Merge branch 'fix/4678' of https://github.com/cjbland/parse-server in…
cjbland Jun 16, 2018
ae3ce3b
Merge branch 'master' into fix/4678
cjbland Jun 18, 2018
da3afbb
Handling the $group operator similar to $match and $project
cjbland Jun 19, 2018
a7c428d
Added more tests for better code coverage
cjbland Jun 20, 2018
cc25079
Excluding certain tests from being run on postgres
cjbland Jun 20, 2018
1a51a82
Excluding one more test from postgres
cjbland Jun 21, 2018
af531c1
clean up
dplewis Jun 24, 2018
6b8fded
Merge branch 'master' into fix/4678
dplewis Jun 26, 2018
f8d7826
Merge branch 'master' into fix/4678
dplewis Jun 26, 2018
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
54 changes: 54 additions & 0 deletions spec/ParseQuery.Aggregate.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,60 @@ describe('Parse.Query Aggregate testing', () => {
});
});

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) => {
expect(results.length).toEqual(2);
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) => {
expect(results.length).toEqual(2);
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('project query', (done) => {
const options = Object.assign({}, masterKeyOptions, {
body: {
Expand Down
62 changes: 50 additions & 12 deletions src/Adapters/Storage/Mongo/MongoStorageAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -565,18 +565,7 @@ export class MongoStorageAdapter implements StorageAdapter {
}
}
if (stage.$match) {
for (const field in stage.$match) {
if (schema.fields[field] && schema.fields[field].type === 'Pointer') {
const transformMatch = { [`_p_${field}`] : `${schema.fields[field].targetClass}$${stage.$match[field]}` };
stage.$match = transformMatch;
}
if (field === 'objectId') {
const transformMatch = Object.assign({}, stage.$match);
transformMatch._id = stage.$match[field];
delete transformMatch.objectId;
stage.$match = transformMatch;
}
}
this._parseAggregateArgs(schema, stage.$match);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returned value seem unused.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking up on that...I was trying to hurry and pushed the repo by accident (muscle memory from my day job, haha). I just pushed the fix.

}
return stage;
});
Expand Down Expand Up @@ -608,6 +597,55 @@ export class MongoStorageAdapter implements StorageAdapter {
.catch(err => this.handleError(err));
}

_parseAggregateArgs(schema: any, pipeline: any): any {
var rtnval = {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use const, and actually remove :)

if (Array.isArray(pipeline)) {
rtnval = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we transform in

return pipeline.map((value) => this._parseAggregateArgs(schema, value));

for (const field in pipeline) {
rtnval.push(this._parseAggregateArgs(schema, pipeline[field]));
}
}
else if (typeof pipeline === 'object') {
for (const field in pipeline) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

declare const returnValue = {} here and update all fields please

if (schema.fields[field] && schema.fields[field].type === 'Pointer') {
rtnval[`_p_${field}`] = `${schema.fields[field].targetClass}$${pipeline[field]}`;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

throughout the codebase we always write

if  {

} else if ... {

} else if ... {

}

Can we keep the style please?

else if (schema.fields[field] && schema.fields[field].type === 'Date') {
rtnval[field] = this._convertToDate(pipeline[field]);
}
else {
rtnval[field] = this._parseAggregateArgs(schema, pipeline[field]);
}

if (field === 'objectId') {
rtnval['_id'] = rtnval[field];
delete rtnval[field];
}
else if (field === 'createdAt') {
rtnval['_created_at'] = rtnval[field];
delete rtnval[field];
}
else if (field === 'updatedAt') {
rtnval['_updated_at'] = rtnval[field];
delete rtnval[field];
}
}
}
return rtnval;
}

_convertToDate(value: any): any {
if (typeof value === 'string') {
return new Date(value);
}

var rtnval = {}
for (const field in value) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we document what we expect the value to look like, I have trouble understanding what it does, and why we need the iterator, and recursion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the newbie question...how do we take care of these? I've updated my branch to include your suggestions. Thanks.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function may work wrong way when "value" is
{ $exists: false }

rtnval[field] = this._convertToDate(value[field])
}
return rtnval;
}

_parseReadPreference(readPreference: ?string): ?string {
switch (readPreference) {
case 'PRIMARY':
Expand Down