Skip to content

News methods for ParseQuery - whereMatchesKeyInQuery and whereDoesNotMatchKeyInQuery #379

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 4 commits into from
May 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<ParseObject> lotsOfWins =
QueryBuilder<ParseObject>(playerObject))
..whereGreaterThan('wins', 50);

QueryBuilder<ParseObject> fewWins =
QueryBuilder<ParseObject>(playerObject)
..whereLessThan('wins', 5);

QueryBuilder<ParseObject> mainQuery = QueryBuilder.or(
playerObject,
[lotsOfWins, fewWins],
);

var apiResponse = await mainQuery.query();
```

The features available are:-
* Equals
* Contains
Expand All @@ -263,6 +283,10 @@ The features available are:-
* WithinKilometers
* WithinRadians
* WithinGeoBox
* MatchesQuery
* DoesNotMatchQuery
* MatchesKeyInQuery
* DoesNotMatchKeyInQuery
* Regex
* Order
* Limit
Expand Down Expand Up @@ -306,6 +330,47 @@ QueryBuilder<ParseObject> 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<ParseObject> teamQuery =
QueryBuilder<ParseObject>(ParseObject('Team'))
..whereGreaterThan('winPct', 0.5);

QueryBuilder<ParseUser> userQuery =
QueryBuilder<ParseUser>ParseUser.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<ParseObject> teamQuery =
QueryBuilder<ParseObject>(ParseObject('Team'))
..whereGreaterThan('winPct', 0.5);

QueryBuilder<ParseUser> losingUserQuery =
QueryBuilder<ParseUser>ParseUser.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<ParseObject> rolesOfTypeX =
QueryBuilder<ParseObject>(ParseObject('Role'))
..whereEqualTo('type', 'x');

QueryBuilder<ParseObject> groupsWithRoleX =
QueryBuilder<ParseObject>(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:

Expand Down
48 changes: 48 additions & 0 deletions lib/src/network/parse_query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,48 @@ class QueryBuilder<T extends ParseObject> {
_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.
// 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, keyInQuery);

queries.add(MapEntry<String, dynamic>(
_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
// ignore: always_specify_types
void whereDoesNotMatchKeyInQuery(
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, keyInQuery);

queries.add(MapEntry<String, dynamic>(
_SINGLE_QUERY, '\"$column\":{\"\$dontSelect\":$inQuery}'));
}

/// Finishes the query and calls the server
///
/// Make sure to call this after defining your queries
Expand Down Expand Up @@ -328,6 +370,12 @@ class QueryBuilder<T extends ParseObject> {
return '{\"where\":{${buildQueries(queries)}},\"className\":\"$className\"${getLimitersRelational(limiters)}}';
}

/// Builds the query relational with Key for Parse
String _buildQueryRelationalKey(String className, String keyInQuery) {
queries = _checkForMultipleColumnInstances(queries);
return '{\"query\":{\"className\":\"$className\",\"where\":{${buildQueries(queries)}}},\"key\":\"$keyInQuery\"}';
}

/// Builds the query for Parse
String _buildQueryCount() {
queries = _checkForMultipleColumnInstances(queries);
Expand Down