From b4b949cf5b4924586b18a2e6bd756e925cd5df59 Mon Sep 17 00:00:00 2001 From: Rodrigo de Souza Marques Date: Sat, 16 May 2020 00:58:44 -0300 Subject: [PATCH 1/4] Add method whereMatchesKeyInQuery Add method whereMatchesKeyInQuery --- lib/src/network/parse_query.dart | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/src/network/parse_query.dart b/lib/src/network/parse_query.dart index 90af6f513..64c5c9705 100644 --- a/lib/src/network/parse_query.dart +++ b/lib/src/network/parse_query.dart @@ -298,6 +298,16 @@ class QueryBuilder { _SINGLE_QUERY, '\"$column\":{\"\$notInQuery\":$inQuery}')); } + void whereMatchesKeyInQuery( + String column, String keyInQuery, QueryBuilder query) { + final String inQuery = + query._buildQueryRelational(query.object.parseClassName); + + queries.add(MapEntry(_SINGLE_QUERY, + '\"$column\":{\"\$select\":$inQuery},"key":"$keyInQuery\"')); + } + + /// Finishes the query and calls the server /// /// Make sure to call this after defining your queries From d3f95881ed176d64bab7ff840bdb19710ba9e1e7 Mon Sep 17 00:00:00 2001 From: Rodrigo de Souza Marques Date: Sat, 16 May 2020 23:47:12 -0300 Subject: [PATCH 2/4] Update parse_query.dart --- lib/src/network/parse_query.dart | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/src/network/parse_query.dart b/lib/src/network/parse_query.dart index 64c5c9705..44ffa322c 100644 --- a/lib/src/network/parse_query.dart +++ b/lib/src/network/parse_query.dart @@ -297,16 +297,26 @@ class QueryBuilder { queries.add(MapEntry( _SINGLE_QUERY, '\"$column\":{\"\$notInQuery\":$inQuery}')); } - - void whereMatchesKeyInQuery( + //Add a constraint to the query that requires a particular key's value matches a value for a key in the results of another ParseQuery. + void whereMatchesKeyInQuery( String column, String keyInQuery, QueryBuilder query) { final String inQuery = - query._buildQueryRelational(query.object.parseClassName); + query._buildQueryRelationalKey(query.object.parseClassName); queries.add(MapEntry(_SINGLE_QUERY, '\"$column\":{\"\$select\":$inQuery},"key":"$keyInQuery\"')); } + //Add a constraint to the query that requires a particular key's value does not match any value for a key in the results of another ParseQuery + void whereDoesNotMatchKeyInQuery( + String column, String keyInQuery, QueryBuilder query) { + final String inQuery = + query._buildQueryRelationalKey(query.object.parseClassName); + + queries.add(MapEntry(_SINGLE_QUERY, + '\"$column\":{\"\$dontSelect\":$inQuery},"key":"$keyInQuery\"')); + + } /// Finishes the query and calls the server /// @@ -338,6 +348,13 @@ class QueryBuilder { return '{\"where\":{${buildQueries(queries)}},\"className\":\"$className\"${getLimitersRelational(limiters)}}'; } + /// Builds the query relational for Parse + String _buildQueryRelationalKey(String className) { + queries = _checkForMultipleColumnInstances(queries); + return '{\"className\":\"$className\",\"where\":{${buildQueries(queries)}}}}'; + } + + /// Builds the query for Parse String _buildQueryCount() { queries = _checkForMultipleColumnInstances(queries); From e7d7d73f1482199e8923084f7311968cbc944a6b Mon Sep 17 00:00:00 2001 From: Rodrigo de Souza Marques Date: Sun, 17 May 2020 22:15:44 -0300 Subject: [PATCH 3/4] Fix whereMatchesKeyInQuery / whereDoesNotMatchKeyInQuery --- lib/src/network/parse_query.dart | 45 ++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/lib/src/network/parse_query.dart b/lib/src/network/parse_query.dart index 44ffa322c..2ac945587 100644 --- a/lib/src/network/parse_query.dart +++ b/lib/src/network/parse_query.dart @@ -297,25 +297,49 @@ class QueryBuilder { queries.add(MapEntry( _SINGLE_QUERY, '\"$column\":{\"\$notInQuery\":$inQuery}')); } + //Add a constraint to the query that requires a particular key's value matches a value for a key in the results of another ParseQuery. + // Add a constraint to the query that requires a particular key's value match another QueryBuilder + // ignore: always_specify_types void whereMatchesKeyInQuery( String column, String keyInQuery, QueryBuilder query) { + if (query.queries.isEmpty) { + throw ArgumentError('query conditions is required'); + } + if (limiters.containsKey('order')) { + throw ArgumentError('order is not allowed'); + } + if (limiters.containsKey('include')) { + throw ArgumentError('include is not allowed'); + } + final String inQuery = - query._buildQueryRelationalKey(query.object.parseClassName); + query._buildQueryRelationalKey(query.object.parseClassName, keyInQuery); - queries.add(MapEntry(_SINGLE_QUERY, - '\"$column\":{\"\$select\":$inQuery},"key":"$keyInQuery\"')); + queries.add(MapEntry( + _SINGLE_QUERY, '\"$column\":{\"\$select\":$inQuery}')); } //Add a constraint to the query that requires a particular key's value does not match any value for a key in the results of another ParseQuery + // Add a constraint to the query that requires a particular key's value match another QueryBuilder + // ignore: always_specify_types void whereDoesNotMatchKeyInQuery( String column, String keyInQuery, QueryBuilder query) { - final String inQuery = - query._buildQueryRelationalKey(query.object.parseClassName); + if (query.queries.isEmpty) { + throw ArgumentError('query conditions is required'); + } + if (limiters.containsKey('order')) { + throw ArgumentError('order is not allowed'); + } + if (limiters.containsKey('include')) { + throw ArgumentError('include is not allowed'); + } - queries.add(MapEntry(_SINGLE_QUERY, - '\"$column\":{\"\$dontSelect\":$inQuery},"key":"$keyInQuery\"')); + final String inQuery = + query._buildQueryRelationalKey(query.object.parseClassName, keyInQuery); + queries.add(MapEntry( + _SINGLE_QUERY, '\"$column\":{\"\$dontSelect\":$inQuery}')); } /// Finishes the query and calls the server @@ -348,13 +372,12 @@ class QueryBuilder { return '{\"where\":{${buildQueries(queries)}},\"className\":\"$className\"${getLimitersRelational(limiters)}}'; } - /// Builds the query relational for Parse - String _buildQueryRelationalKey(String className) { + /// Builds the query relational with Key for Parse + String _buildQueryRelationalKey(String className, String keyInQuery) { queries = _checkForMultipleColumnInstances(queries); - return '{\"className\":\"$className\",\"where\":{${buildQueries(queries)}}}}'; + return '{\"query\":{\"className\":\"$className\",\"where\":{${buildQueries(queries)}}},\"key\":\"$keyInQuery\"}'; } - /// Builds the query for Parse String _buildQueryCount() { queries = _checkForMultipleColumnInstances(queries); From e5b987919434a6a823b86517e600f187de11d14d Mon Sep 17 00:00:00 2001 From: Rodrigo de Souza Marques Date: Tue, 19 May 2020 14:39:00 -0300 Subject: [PATCH 4/4] Update README.md --- README.md | 65 ++++++++++++++++++++++++++++++++ lib/src/network/parse_query.dart | 6 +-- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index dea4a2c0a..2ef456ed0 100644 --- a/README.md +++ b/README.md @@ -247,6 +247,26 @@ if (response.success) { } ``` +if you want to find objects that match one of several queries, you can use __QueryBuilder.or__ method to construct a query that is an OR of the queries passed in. For instance if you want to find players who either have a lot of wins or a few wins, you can do: +```dart +ParseObject playerObject = ParseObject("Player"); + +QueryBuilder lotsOfWins = + QueryBuilder(playerObject)) + ..whereGreaterThan('wins', 50); + +QueryBuilder fewWins = + QueryBuilder(playerObject) + ..whereLessThan('wins', 5); + +QueryBuilder mainQuery = QueryBuilder.or( + playerObject, + [lotsOfWins, fewWins], + ); + +var apiResponse = await mainQuery.query(); +``` + The features available are:- * Equals * Contains @@ -263,6 +283,10 @@ The features available are:- * WithinKilometers * WithinRadians * WithinGeoBox + * MatchesQuery + * DoesNotMatchQuery + * MatchesKeyInQuery + * DoesNotMatchKeyInQuery * Regex * Order * Limit @@ -306,6 +330,47 @@ QueryBuilder queryComment = var apiResponse = await queryComment.query(); ``` +You can use the __whereMatchesKeyInQuery__ method to get objects where a key matches the value of a key in a set of objects resulting from another query. For example, if you have a class containing sports teams and you store a user’s hometown in the user class, you can issue one query to find the list of users whose hometown teams have winning records. The query would look like:: + +```dart +QueryBuilder teamQuery = + QueryBuilder(ParseObject('Team')) + ..whereGreaterThan('winPct', 0.5); + +QueryBuilder userQuery = + QueryBuilderParseUser.forQuery()) + ..whereMatchesKeyInQuery('hometown', 'city', teamQuery); + +var apiResponse = await userQuery.query(); +``` + +Conversely, to get objects where a key does not match the value of a key in a set of objects resulting from another query, use __whereDoesNotMatchKeyInQuery__. For example, to find users whose hometown teams have losing records: + +```dart +QueryBuilder teamQuery = + QueryBuilder(ParseObject('Team')) + ..whereGreaterThan('winPct', 0.5); + +QueryBuilder losingUserQuery = + QueryBuilderParseUser.forQuery()) + ..whereDoesNotMatchKeyInQuery('hometown', 'city', teamQuery); + +var apiResponse = await losingUserQuery.query(); +``` + +To filter rows based on objectId’s from pointers in a second table, you can use dot notation: +```dart +QueryBuilder rolesOfTypeX = + QueryBuilder(ParseObject('Role')) + ..whereEqualTo('type', 'x'); + +QueryBuilder groupsWithRoleX = + QueryBuilder(ParseObject('Group'))) + ..whereMatchesKeyInQuery('objectId', 'belongsTo.objectId', rolesOfTypeX); + +var apiResponse = await groupsWithRoleX.query(); +``` + ## Counting Objects If you only care about the number of games played by a particular player: diff --git a/lib/src/network/parse_query.dart b/lib/src/network/parse_query.dart index 2ac945587..71d6e4c47 100644 --- a/lib/src/network/parse_query.dart +++ b/lib/src/network/parse_query.dart @@ -298,8 +298,7 @@ class QueryBuilder { _SINGLE_QUERY, '\"$column\":{\"\$notInQuery\":$inQuery}')); } - //Add a constraint to the query that requires a particular key's value matches a value for a key in the results of another ParseQuery. - // Add a constraint to the query that requires a particular key's value match another QueryBuilder + // Add a constraint to the query that requires a particular key's value matches a value for a key in the results of another ParseQuery. // ignore: always_specify_types void whereMatchesKeyInQuery( String column, String keyInQuery, QueryBuilder query) { @@ -320,8 +319,7 @@ class QueryBuilder { _SINGLE_QUERY, '\"$column\":{\"\$select\":$inQuery}')); } - //Add a constraint to the query that requires a particular key's value does not match any value for a key in the results of another ParseQuery - // Add a constraint to the query that requires a particular key's value match another QueryBuilder + // Add a constraint to the query that requires a particular key's value does not match any value for a key in the results of another ParseQuery // ignore: always_specify_types void whereDoesNotMatchKeyInQuery( String column, String keyInQuery, QueryBuilder query) {