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

Conversation

cjbland
Copy link
Contributor

@cjbland cjbland commented Apr 30, 2018

I added a check to see if the schema field is a Date. If so, convert the string into a Date object which the mongodb driver will accept for the aggregate function (it will not accept strings). I also added checks for the createdAt and updatedAt attributes and converted them to the actual column names.

Copy link
Contributor

@flovilmart flovilmart left a comment

Choose a reason for hiding this comment

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

The code look good, can you add tests to ensure we cover all those 3 code paths and don’t introduce any regression in the future?

@codecov
Copy link

codecov bot commented Apr 30, 2018

Codecov Report

Merging #4743 into master will increase coverage by 0.04%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #4743      +/-   ##
==========================================
+ Coverage   92.77%   92.81%   +0.04%     
==========================================
  Files         119      119              
  Lines        8760     8813      +53     
==========================================
+ Hits         8127     8180      +53     
  Misses        633      633
Impacted Files Coverage Δ
src/Adapters/Storage/Mongo/MongoStorageAdapter.js 92.03% <100%> (+1.2%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3ace26d...f8d7826. Read the comment docs.

@cjbland
Copy link
Contributor Author

cjbland commented Apr 30, 2018

I need to keep working on this, I had forgotten about the other operators such as $gt, $gte, etc.

@flovilmart
Copy link
Contributor

@cjbland no worry! Thanks for your contributions!

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.

Copy link
Contributor

@flovilmart flovilmart left a comment

Choose a reason for hiding this comment

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

Thanks for the PR. I did a first pass at the review, so if we can get the style + a bit of comments on the hard parts that would be very appreciated ;)

_parseAggregateArgs(schema: any, pipeline: any): any {
var rtnval = {};
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));

@@ -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 :)

}
}
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

for (const field in pipeline) {
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?

}

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 }

@flovilmart
Copy link
Contributor

@cjbland also it seems that many tests are failing :) You can run them locally with npm test spec/ParseQuery.Aggregate.spec.js so only the aggregate suite is run!

@cjbland
Copy link
Contributor Author

cjbland commented May 2, 2018

Thanks for the tip. I didn't realize the tests were failing but I see them now. I'll also fix the styling and take care of the other comments you've made. Thanks for taking your time to review this and sorry I'm not making it a little easier for you.

@dplewis
Copy link
Member

dplewis commented May 2, 2018

@cjbland Thanks for getting this PR in. I started something like this a while ago and maybe we can collaborate on this. You can reuse whats in the MongoTransform.js for most of the transform keys.

Here is my branch.
https://github.com/dplewis/parse-server/tree/aggregate-recursive

@flovilmart
Copy link
Contributor

@dplewis do you want to take-over with @cjbland on this PR? Perhaps @cjbland , you could get back on the aggregate-recursive branch and see if your use case is solved. What were you planing @dplewis ? I know you've been busy lately with other things.

@dplewis
Copy link
Member

dplewis commented May 2, 2018

@flovilmart I noticed 3-4 open issues and a lot of users requested transforming keys like pointers, default fields, and dates. I was trying to handle all use cases but I kinda lack complex aggregate queries to ensure it works.

The current transform code is getting to be too much to handle considering there are ~40 mongo aggregate stages and could use some refactoring.

The stages could be broken down as follows.

// { limit: 1 }
{ stageName: value}

// value can be any type or $field
// { group : { objectId: '' }
// { group: { objectId: '$name' }
{ stageName: { field: value }

// { match: { pointer: { $exist: true } } }
{ stageName: { field: { op: value } }

// group: { total: { $sum: '$score' } },
{ stageName: { newField: { op: value } }

// match: { $or: [{ score: { $gt: 15, $lt: 25 } }, { views: { $gt: 750, $lt: 850 } }]}
{ stageName: { op: value } 

There maybe more that I don't know of. I can submit a PR and worry about complex queries as they come along.

Here's an example of the most complex aggregate I've used. #1908 (comment)

@cjbland
Copy link
Contributor Author

cjbland commented May 3, 2018

I'm definitely open to collaborating. The recursive aggregate function I wrote seems to work, my issue is the test case... I don't have any experience writing these tests, but I feel like the previous tests' TestObjects are being returned when I wasn't expecting them. Any pointers on how best to debug something like that?

@dplewis
Copy link
Member

dplewis commented May 3, 2018

@cjbland For sure, checkout the Contributing.MD for running test cases.
https://github.com/parse-community/parse-server/blob/master/CONTRIBUTING.md

There is a function loadTestData() that gets called before each test.

https://github.com/parse-community/parse-server/blob/master/spec/ParseQuery.Aggregate.spec.js#L20

Thats where your TestObjects are coming from. Keep in mind that those objects exists

@cjbland
Copy link
Contributor Author

cjbland commented May 4, 2018

I added some comments to hopefully document my approach here. Personally, I'm not a fan of recursion, but this seems like the perfect candidate for it. The goal was to treat the query like a tree and traverse the tree to get to the leaf nodes. Once at the leaf node determine whether or not the value needed to be converted (based on the schema). I understand the structure isn't exactly a tree, but that's the best way for me to describe my intent. This should also handle any of the aggregation cases (since we aren't looking specifically for pipeline or comparison operators).

@dplewis
Copy link
Member

dplewis commented May 16, 2018

@cjbland I like your approach better. Can you copy the tests from my branch to see if they run?

@cjbland
Copy link
Contributor Author

cjbland commented May 17, 2018

Absolutely. Give me a few days, I have a lot going on this week.

Copy link
Contributor Author

@cjbland cjbland left a comment

Choose a reason for hiding this comment

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

I've addressed these changes in the most recent commits.

@cjbland
Copy link
Contributor Author

cjbland commented Jun 20, 2018

I made the change that @dplewis suggested and added more tests for better code coverage. Hopefully this gets us a little closer.

@cjbland
Copy link
Contributor Author

cjbland commented Jun 20, 2018

Is there documentation on which of these aggregate functions are supported by PostgreSQL? That seems to be why the latest tests failed for test 6417.3 - it didn't know how to handle the $exists operator.

@dplewis
Copy link
Member

dplewis commented Jun 20, 2018

@cjbland that’s the reason why that test was excluded. Postgres only supports basic aggregates aka 3 stages no operators

@cjbland
Copy link
Contributor Author

cjbland commented Jun 22, 2018

I'm happier with this now. Let me know what the next steps are. Thanks guys!

@dplewis
Copy link
Member

dplewis commented Jun 26, 2018

@flovilmart I did some linter clean up can you do a final review?

Copy link
Contributor

@flovilmart flovilmart left a comment

Choose a reason for hiding this comment

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

Let's go!

@dplewis
Copy link
Member

dplewis commented Jun 26, 2018

@cjbland Thanks for the PR

@cjbland
Copy link
Contributor Author

cjbland commented Jun 26, 2018

No problem, thanks for your patience. I’d like to contribute more if needed.

@flovilmart
Copy link
Contributor

@cjbland, thanks! Contributions can take many forms, and we always encourage people who want to start contributing a bit more to respond on some issues. If you feel you can address a few of the open ones, i’ll Gladly walk you through it and give the appropriate accesses so you can close / label them!

@dplewis dplewis merged commit 5cdbde2 into parse-community:master Jun 26, 2018
@EricNetsch
Copy link

EricNetsch commented Aug 12, 2018

@dplewis @flovilmart
Looks like this was released into 2.8.3 but not seeing the new code on my side when updating/reinstalling. Really strange since I even see the new code when I download the new 2.8.3 zip.

Any ideas on what's going on?
Thanks!

@flovilmart
Copy link
Contributor

I wasn't released part of 2.8.3 as this version is a hotfix for compatibility with the JS SDK.

2.8.2...2.8.3

@EricNetsch
Copy link

@flovilmart Got it. Saw it in the release commits so assumed it was part of 2.8.3 .
Any idea on when we can release this fix?

Thanks for clarifying,
screenshot 2018-08-11 17 47 47

@flovilmart
Copy link
Contributor

We’re working on the 3.0 at the moment, and it’s likely gonna be the next release. Perhaps there will be a 2.8.4 before we cut the 3.0

@EricNetsch
Copy link

Got it thanks.
Ahh I see I was looking at master commits since 2.8.3 lol. Confusing UX on github releases.
Appreciate it.

@flovilmart
Copy link
Contributor

It’s always unlikely a release is ahead of master :)

flovilmart pushed a commit that referenced this pull request Aug 12, 2018
#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
flovilmart pushed a commit that referenced this pull request Aug 12, 2018
#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
UnderratedDev pushed a commit to UnderratedDev/parse-server that referenced this pull request Mar 21, 2020
…Date within agg… (parse-community#4743)

* parse-community#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
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 5.0.0-beta.1

@parseplatformorg parseplatformorg added the state:released-beta Released as beta version label Nov 1, 2021
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 5.0.0

@parseplatformorg parseplatformorg added the state:released Released as stable version label Mar 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
state:released Released as stable version state:released-beta Released as beta version
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants