Skip to content

Commit 58cd228

Browse files
News methods for ParseQuery - whereMatchesKeyInQuery and whereDoesNotMatchKeyInQuery (#379)
* Add method whereMatchesKeyInQuery Add method whereMatchesKeyInQuery * Update parse_query.dart * Fix whereMatchesKeyInQuery / whereDoesNotMatchKeyInQuery * Update README.md
1 parent 023d98c commit 58cd228

File tree

2 files changed

+113
-0
lines changed

2 files changed

+113
-0
lines changed

README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,26 @@ if (response.success) {
247247
}
248248
```
249249

250+
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:
251+
```dart
252+
ParseObject playerObject = ParseObject("Player");
253+
254+
QueryBuilder<ParseObject> lotsOfWins =
255+
QueryBuilder<ParseObject>(playerObject))
256+
..whereGreaterThan('wins', 50);
257+
258+
QueryBuilder<ParseObject> fewWins =
259+
QueryBuilder<ParseObject>(playerObject)
260+
..whereLessThan('wins', 5);
261+
262+
QueryBuilder<ParseObject> mainQuery = QueryBuilder.or(
263+
playerObject,
264+
[lotsOfWins, fewWins],
265+
);
266+
267+
var apiResponse = await mainQuery.query();
268+
```
269+
250270
The features available are:-
251271
* Equals
252272
* Contains
@@ -263,6 +283,10 @@ The features available are:-
263283
* WithinKilometers
264284
* WithinRadians
265285
* WithinGeoBox
286+
* MatchesQuery
287+
* DoesNotMatchQuery
288+
* MatchesKeyInQuery
289+
* DoesNotMatchKeyInQuery
266290
* Regex
267291
* Order
268292
* Limit
@@ -306,6 +330,47 @@ QueryBuilder<ParseObject> queryComment =
306330
var apiResponse = await queryComment.query();
307331
```
308332

333+
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::
334+
335+
```dart
336+
QueryBuilder<ParseObject> teamQuery =
337+
QueryBuilder<ParseObject>(ParseObject('Team'))
338+
..whereGreaterThan('winPct', 0.5);
339+
340+
QueryBuilder<ParseUser> userQuery =
341+
QueryBuilder<ParseUser>ParseUser.forQuery())
342+
..whereMatchesKeyInQuery('hometown', 'city', teamQuery);
343+
344+
var apiResponse = await userQuery.query();
345+
```
346+
347+
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:
348+
349+
```dart
350+
QueryBuilder<ParseObject> teamQuery =
351+
QueryBuilder<ParseObject>(ParseObject('Team'))
352+
..whereGreaterThan('winPct', 0.5);
353+
354+
QueryBuilder<ParseUser> losingUserQuery =
355+
QueryBuilder<ParseUser>ParseUser.forQuery())
356+
..whereDoesNotMatchKeyInQuery('hometown', 'city', teamQuery);
357+
358+
var apiResponse = await losingUserQuery.query();
359+
```
360+
361+
To filter rows based on objectId’s from pointers in a second table, you can use dot notation:
362+
```dart
363+
QueryBuilder<ParseObject> rolesOfTypeX =
364+
QueryBuilder<ParseObject>(ParseObject('Role'))
365+
..whereEqualTo('type', 'x');
366+
367+
QueryBuilder<ParseObject> groupsWithRoleX =
368+
QueryBuilder<ParseObject>(ParseObject('Group')))
369+
..whereMatchesKeyInQuery('objectId', 'belongsTo.objectId', rolesOfTypeX);
370+
371+
var apiResponse = await groupsWithRoleX.query();
372+
```
373+
309374
## Counting Objects
310375
If you only care about the number of games played by a particular player:
311376

lib/src/network/parse_query.dart

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,48 @@ class QueryBuilder<T extends ParseObject> {
298298
_SINGLE_QUERY, '\"$column\":{\"\$notInQuery\":$inQuery}'));
299299
}
300300

301+
// 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.
302+
// ignore: always_specify_types
303+
void whereMatchesKeyInQuery(
304+
String column, String keyInQuery, QueryBuilder query) {
305+
if (query.queries.isEmpty) {
306+
throw ArgumentError('query conditions is required');
307+
}
308+
if (limiters.containsKey('order')) {
309+
throw ArgumentError('order is not allowed');
310+
}
311+
if (limiters.containsKey('include')) {
312+
throw ArgumentError('include is not allowed');
313+
}
314+
315+
final String inQuery =
316+
query._buildQueryRelationalKey(query.object.parseClassName, keyInQuery);
317+
318+
queries.add(MapEntry<String, dynamic>(
319+
_SINGLE_QUERY, '\"$column\":{\"\$select\":$inQuery}'));
320+
}
321+
322+
// 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
323+
// ignore: always_specify_types
324+
void whereDoesNotMatchKeyInQuery(
325+
String column, String keyInQuery, QueryBuilder query) {
326+
if (query.queries.isEmpty) {
327+
throw ArgumentError('query conditions is required');
328+
}
329+
if (limiters.containsKey('order')) {
330+
throw ArgumentError('order is not allowed');
331+
}
332+
if (limiters.containsKey('include')) {
333+
throw ArgumentError('include is not allowed');
334+
}
335+
336+
final String inQuery =
337+
query._buildQueryRelationalKey(query.object.parseClassName, keyInQuery);
338+
339+
queries.add(MapEntry<String, dynamic>(
340+
_SINGLE_QUERY, '\"$column\":{\"\$dontSelect\":$inQuery}'));
341+
}
342+
301343
/// Finishes the query and calls the server
302344
///
303345
/// Make sure to call this after defining your queries
@@ -328,6 +370,12 @@ class QueryBuilder<T extends ParseObject> {
328370
return '{\"where\":{${buildQueries(queries)}},\"className\":\"$className\"${getLimitersRelational(limiters)}}';
329371
}
330372

373+
/// Builds the query relational with Key for Parse
374+
String _buildQueryRelationalKey(String className, String keyInQuery) {
375+
queries = _checkForMultipleColumnInstances(queries);
376+
return '{\"query\":{\"className\":\"$className\",\"where\":{${buildQueries(queries)}}},\"key\":\"$keyInQuery\"}';
377+
}
378+
331379
/// Builds the query for Parse
332380
String _buildQueryCount() {
333381
queries = _checkForMultipleColumnInstances(queries);

0 commit comments

Comments
 (0)