Skip to content

New query condition support to match all strings that starts with some other given strings #3864

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

Conversation

eduardbosch
Copy link
Contributor

Hi to all! 🎉

This changes gives support to this contributions:
parse-community/Parse-SDK-Android#673
and
parse-community/Parse-SDK-JS#437

It allows to send regular expressions with $all query.

Please, read this link to know why I need this changes in the server:

parse-community/Parse-SDK-Android#673

Thanks a lot 😀

@flovilmart
Copy link
Contributor

Thanks for the PR, this looks great but could you add proper edge to edge test with it_only_db('mongo') so we don't run it on Postgres. @vitaly-t do you think this could work on PG as well?

@flovilmart flovilmart self-requested a review May 28, 2017 16:50
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.

Edge to edge tests would be nice, postgres support would be awesome.

@vitaly-t
Copy link
Contributor

@flovilmart I can't really say. I haven't actually used parse-server for anything yet. Just doing support as far as pg-promise is concerned.

@codecov
Copy link

codecov bot commented May 28, 2017

Codecov Report

Merging #3864 into master will increase coverage by 0.32%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3864      +/-   ##
==========================================
+ Coverage   90.14%   90.47%   +0.32%     
==========================================
  Files         114      114              
  Lines        7550     7684     +134     
==========================================
+ Hits         6806     6952     +146     
+ Misses        744      732      -12
Impacted Files Coverage Δ
src/Adapters/Storage/Mongo/MongoTransform.js 83.56% <100%> (+0.59%) ⬆️
src/Controllers/SchemaController.js 97.05% <0%> (ø) ⬆️
src/Controllers/DatabaseController.js 94.35% <0%> (+0.01%) ⬆️
src/RestQuery.js 94.94% <0%> (+0.02%) ⬆️
src/Adapters/Storage/Mongo/MongoStorageAdapter.js 92.98% <0%> (+0.08%) ⬆️
src/Routers/ClassesRouter.js 93.05% <0%> (+0.09%) ⬆️
src/rest.js 97.18% <0%> (+0.16%) ⬆️
...dapters/Storage/Postgres/PostgresStorageAdapter.js 95.83% <0%> (+0.37%) ⬆️
src/Adapters/Storage/Mongo/MongoCollection.js 95.12% <0%> (+0.38%) ⬆️
src/RestWrite.js 93.29% <0%> (+0.42%) ⬆️
... and 7 more

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 1f11ad5...c3921f3. Read the comment docs.

@@ -320,6 +320,9 @@ describe('parseObjectToMongoObjectForCreate', () => {
done();
});

});

describe_only_db('mongo')('parseObjectToMongoObjectForCreate', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I was thinking about an edge to edge test case, with proper data (create multiple objects and run the query). Do you think that's possible?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was writing you to ask if this was what you where asking for. I don't know how to make this tests. Is there any edge to edge test case in the repository? Sorry, I'm not really familiar with Jasmine.

If you tell me how to make this tests or where to take an idea, I'll take a look for sure.

Do you think I should rollback this change??

Copy link
Contributor

Choose a reason for hiding this comment

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

Do you think I should rollback this change??

You can roll it back, but that doesn't really change anything.

The edge to edge test would look like:

it('should match all strings that starts with string', (done) => {
  let object = new Parse.Object('Object');
  object.set('strings', ['the', 'brown', 'fox', 'jumps']);
  let object2 = new Parse.Object('Object');
  object2.set('strings', ['over', 'the', 'lazy', 'dog']);
  Parse.Object.saveAll([object, object2]).then(() => {
   return request.get({
      url: Parse.serverURL + 'classes/Object',
      json: true,
      query: ... // build the JSON query
   });
  }).then((results) => {
     expect(....) // TODO: validate the results
  });
}); 

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 @flovilmart

I'll make this tests when I have some time!

@eduardbosch
Copy link
Contributor Author

I've added the tests with containsAllStartingWith function. To simplify the tests, I updated the parse dependency to the one I've implemented the containsAllStartingWith for Parse JS SDK.

Sorry for the delay, but I'm so busy this days.

Let me know the next steps ☺️

@flovilmart
Copy link
Contributor

@eduardbosch any chance you'd get it to work with postgres? I know that regexp support is not 💯 in PG, so perhaps you should just replace it by it_exclude_dbs(['postgres'])

@dplewis
Copy link
Member

dplewis commented Jun 27, 2017

@eduardbosch @flovilmart I have this working for postgres. You can find a solution on my branch.

dplewis@bc449e9

You may have to add some validation on postgres transform and a few more edge to edge tests to be sure.

@codecov-io
Copy link

codecov-io commented Jul 7, 2017

Codecov Report

Merging #3864 into master will increase coverage by <.01%.
The diff coverage is 95.83%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3864      +/-   ##
==========================================
+ Coverage   92.66%   92.66%   +<.01%     
==========================================
  Files         119      119              
  Lines        8585     8632      +47     
==========================================
+ Hits         7955     7999      +44     
- Misses        630      633       +3
Impacted Files Coverage Δ
src/Adapters/Storage/Postgres/sql/index.js 87.5% <ø> (ø) ⬆️
...dapters/Storage/Postgres/PostgresStorageAdapter.js 97.2% <95.65%> (-0.04%) ⬇️
src/Adapters/Storage/Mongo/MongoTransform.js 86.54% <96%> (+0.38%) ⬆️
src/Routers/PushRouter.js 92.85% <0%> (-3.58%) ⬇️
src/RestWrite.js 93.41% <0%> (ø) ⬆️

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 2c357df...917ec15. Read the comment docs.

@eduardbosch eduardbosch force-pushed the feat/contains-all-starting-with branch 2 times, most recently from 7e36fb1 to 132b0d6 Compare July 7, 2017 15:23
@eduardbosch
Copy link
Contributor Author

@dplewis Thanks for the changes. I've added to the PR.

@flovilmart Do you know why Travis is not checking the integration? I'm new to Travis, so I'm not really sure what's happening. I think postgres tests should work with @dplewis changes now.

In the other hand, I would like to know how to add tests to check progress for regex transform.

Thanks to all and sorry for the delay. I'll like to fix all this 😛

@dplewis
Copy link
Member

dplewis commented Jul 7, 2017

@eduardbosch Can you make a test for REST similar to ParseQuery.spec
https://github.com/parse-community/parse-server/blob/master/spec/ParseQuery.spec.js#L2914

The following should throw an error. Every object of $all should check for $regex for containsAllStartingWith to work

where: {
  strings: {
    $all: [
      {$regex: ...},
      {$regex: ...},
      {$unknown: ...}
    ]
  }
}

@eduardbosch
Copy link
Contributor Author

eduardbosch commented Jul 7, 2017

@dplewis Now parse server checks that all values in $all must be of type {$regex: '^\Qstring\E'} or none.

I've added also a REST test for containsAllStartingWith.

package.json Outdated
@@ -29,7 +29,7 @@
"mime": "1.3.6",
"mongodb": "2.2.26",
"multer": "1.3.0",
"parse": "1.9.2",
"parse": "eduardbosch/Parse-SDK-JS#contains-all-starting-with",
Copy link
Member

Choose a reason for hiding this comment

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

Since you are using REST the JavaScript branch isn't needed. Changing it back will remove the conflict also.

.then(function (results) {
equal(results.results.length, 1);

return require('request-promise').get({
Copy link
Member

Choose a reason for hiding this comment

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

Move this to a separate test for errors

equal(objectList.length, results.length);

new Parse.Query('Object')
.containsAllStartingWith('strings', ['the', 'fox', 'lazy'])
Copy link
Member

Choose a reason for hiding this comment

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

REST covers this you can remove the .containsAllStartingWith

@@ -44,6 +44,30 @@ const transformObjectACL = ({ ACL, ...result }) => {

const specialQuerykeys = ['$and', '$or', '_rperm', '_wperm', '_perishable_token', '_email_verify_token', '_email_verify_token_expires_at', '_account_lockout_expires_at', '_failed_login_count'];

const isStartsWith = value => {
Copy link
Member

Choose a reason for hiding this comment

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

Can you move the checks from the controller to the adapters?

@@ -307,7 +307,15 @@ const buildWhereClause = ({ schema, query, index }) => {
}

if (Array.isArray(fieldValue.$all) && isArrayField) {
patterns.push(`array_contains_all($${index}:name, $${index + 1}::jsonb)`);
if (fieldValue.$all[0].$regex) {
Copy link
Member

Choose a reason for hiding this comment

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

Here I just checked the first index but you can loop through and check all fields instead of checking on the controller

Copy link
Member

Choose a reason for hiding this comment

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

The same can be done for mongo

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's alredy done for Mongo too 🙂

@eduardbosch
Copy link
Contributor Author

@dplewis tests added

I've added some tests to spec/MongoTransform.spec.js also.

I had to setup different tests for Postgres and Mongo as containsAll works differently in both databases.

Maybe would be better to try to unify the same functionality for both databases?

}
});
})
.then(function () {
Copy link
Member

Choose a reason for hiding this comment

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

@eduardbosch I figured they would return different values for both databases. Some of your tests are missing .then() return values. If you add the return values for PG I can look at the script I wrote to see if I can get similar functionality to mongo

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dplewis I don't understand. Some miss .then() return values because they throw an error, so that function is never called.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry missed that. Looking at your test, it should be easy to make PG throw an error instead of returning zero results for invalid $all.

@eduardbosch
Copy link
Contributor Author

Sorry for the long delay!

I've unified all functionality from MongoDB and PostgreSQL except when the $all array is empty.

In MongoDB returns an empty result but in PostgreSQL returns all results.

Maybe contains-all-regex.sql should be changed to return empty results on empty $all.

@dplewis
Copy link
Member

dplewis commented May 16, 2018

@eduardbosch @flovilmart Sorry for the late reply. The empty $all has another issue here.

query.containAll('field', []) returns all values for PG and have nothing to do with this PR.

Basically contains-all-regex.sql doesn't get called here because there aren't any regex present but contains-all.sql does.

This should be good to merge. I'll create another PR for the empty $all

@flovilmart
Copy link
Contributor

As it stands because there’s no edge to edge tests, it’s passing but adding a proper test would let it fail. Do you believe $nor and $elemMatch would be portable to PG?

@dplewis
Copy link
Member

dplewis commented May 16, 2018

@flovilmart Wrong thread 😜. I can look at it if there are test cases.

@flovilmart
Copy link
Contributor

Oops! Sorry!!

@dplewis
Copy link
Member

dplewis commented May 16, 2018

@eduardbosch Sorry this took almost a year. 🎉. We learned a lot about PG and found a bug. Thanks for the contribution. 🙏

@dplewis
Copy link
Member

dplewis commented May 16, 2018

@flovilmart How does this look?

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.

This is looking good if it’s looking good for you @dplewis!

@dplewis dplewis merged commit c0e3672 into parse-community:master May 16, 2018
@flovilmart
Copy link
Contributor

Thanks @eduardbosch for your commitment and patience!

@eduardbosch
Copy link
Contributor Author

Thanks to you @flovilmart @dplewis for your patience too!! I've learned a lot too 🎉

So happy to see this merged 😍I hope this could be a useful feature for someone.

I think we should start taking a look at the SDKs integrations now:

I'm currently porting my app to iOS, so I think I'll add those changes to the iOS SDK too in a future.

@dplewis dplewis mentioned this pull request May 24, 2018
8 tasks
UnderratedDev pushed a commit to UnderratedDev/parse-server that referenced this pull request Mar 21, 2020
…e other given strings (parse-community#3864)

* feat: Convert $regex value to RegExp object

* feat: Add lib folder

* Revert "feat: Add lib folder"

This reverts commit c9dfbcb.

* feat: Add $regex test in $all array

* test: Test regex with $all only in MongoDB

* Revert "test: Test regex with $all only in MongoDB"

This reverts commit d7194c7.

* feat: Add tests for containsAllStartingWith

* feat: Add postgres support

Thanks to @dplewis

* feat: Check that all values in $all must be regex or none

* test: Check that $all vaules must be regex or none

* feat: Update tests to use only REST API

* refactor: Move $all regex check to adapter

* feat: Check for valid $all values in progres

* refactor: Update function name

* fix:  Postgres $all values regex checking

* fix: Check starts with as string

* fix: Define contains all regex sql function

* fix: Wrong value check

* fix: Check valid data

* fix: Check regex when there is only one value

* fix: Constains all starting with string returns empty with bad params

* fix: Pass correct regex value

* feat: Add missing tests

* feat: Add missing tests

* feat: Add more tests

* fix: Unify MongoDB and PostgreSQL functionality

* fix: Lint checks

* fix: Test broken

$regex in $all list must be { $regex: "string" }

* test for empty $all
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants