Skip to content

Commit 0e5f4e3

Browse files
briblanchkroikie
authored andcommitted
Support for Query.getDocuments (flutter#376)
Add support of retrieving the documents that match a query.
1 parent 3766377 commit 0e5f4e3

File tree

5 files changed

+170
-69
lines changed

5 files changed

+170
-69
lines changed

packages/cloud_firestore/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 0.2.8
2+
* Support for Query.getDocuments
3+
14
## 0.2.7
25

36
* Add transaction support.

packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java

Lines changed: 62 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,45 @@ private DocumentReference getDocumentReference(Map<String, Object> arguments) {
6969
return FirebaseFirestore.getInstance().document(path);
7070
}
7171

72+
private Map<String, Object> parseQuerySnapshot(QuerySnapshot querySnapshot) {
73+
if (querySnapshot == null) return new HashMap<>();
74+
Map<String, Object> data = new HashMap<>();
75+
List<String> paths = new ArrayList<>();
76+
List<Map<String, Object>> documents = new ArrayList<>();
77+
for (DocumentSnapshot document : querySnapshot.getDocuments()) {
78+
paths.add(document.getReference().getPath());
79+
documents.add(document.getData());
80+
}
81+
data.put("paths", paths);
82+
data.put("documents", documents);
83+
84+
List<Map<String, Object>> documentChanges = new ArrayList<>();
85+
for (DocumentChange documentChange : querySnapshot.getDocumentChanges()) {
86+
Map<String, Object> change = new HashMap<>();
87+
String type = null;
88+
switch (documentChange.getType()) {
89+
case ADDED:
90+
type = "DocumentChangeType.added";
91+
break;
92+
case MODIFIED:
93+
type = "DocumentChangeType.modified";
94+
break;
95+
case REMOVED:
96+
type = "DocumentChangeType.removed";
97+
break;
98+
}
99+
change.put("type", type);
100+
change.put("oldIndex", documentChange.getOldIndex());
101+
change.put("newIndex", documentChange.getNewIndex());
102+
change.put("document", documentChange.getDocument().getData());
103+
change.put("path", documentChange.getDocument().getReference().getPath());
104+
documentChanges.add(change);
105+
}
106+
data.put("documentChanges", documentChanges);
107+
108+
return data;
109+
}
110+
72111
private Transaction getTransaction(Map<String, Object> arguments) {
73112
return transactions.get((Integer) arguments.get("transactionId"));
74113
}
@@ -161,41 +200,9 @@ public void onEvent(QuerySnapshot querySnapshot, FirebaseFirestoreException e) {
161200
// TODO: send error
162201
System.out.println(e);
163202
}
164-
Map<String, Object> arguments = new HashMap<>();
165-
arguments.put("handle", handle);
166-
167-
List<String> paths = new ArrayList<>();
168-
List<Map<String, Object>> documents = new ArrayList<>();
169-
for (DocumentSnapshot document : querySnapshot.getDocuments()) {
170-
paths.add(document.getReference().getPath());
171-
documents.add(document.getData());
172-
}
173-
arguments.put("paths", paths);
174-
arguments.put("documents", documents);
175203

176-
List<Map<String, Object>> documentChanges = new ArrayList<>();
177-
for (DocumentChange documentChange : querySnapshot.getDocumentChanges()) {
178-
Map<String, Object> change = new HashMap<>();
179-
String type = null;
180-
switch (documentChange.getType()) {
181-
case ADDED:
182-
type = "DocumentChangeType.added";
183-
break;
184-
case MODIFIED:
185-
type = "DocumentChangeType.modified";
186-
break;
187-
case REMOVED:
188-
type = "DocumentChangeType.removed";
189-
break;
190-
}
191-
change.put("type", type);
192-
change.put("oldIndex", documentChange.getOldIndex());
193-
change.put("newIndex", documentChange.getNewIndex());
194-
change.put("document", documentChange.getDocument().getData());
195-
change.put("path", documentChange.getDocument().getReference().getPath());
196-
documentChanges.add(change);
197-
}
198-
arguments.put("documentChanges", documentChanges);
204+
Map<String, Object> arguments = parseQuerySnapshot(querySnapshot);
205+
arguments.put("handle", handle);
199206

200207
channel.invokeMethod("QuerySnapshot", arguments);
201208
}
@@ -387,6 +394,27 @@ protected Void doInBackground(Void... voids) {
387394
result.success(null);
388395
break;
389396
}
397+
case "Query#getDocuments":
398+
{
399+
Map<String, Object> arguments = call.arguments();
400+
Query query = getQuery(arguments);
401+
Task<QuerySnapshot> task = query.get();
402+
task.addOnSuccessListener(
403+
new OnSuccessListener<QuerySnapshot>() {
404+
@Override
405+
public void onSuccess(QuerySnapshot querySnapshot) {
406+
result.success(parseQuerySnapshot(querySnapshot));
407+
}
408+
})
409+
.addOnFailureListener(
410+
new OnFailureListener() {
411+
@Override
412+
public void onFailure(@NonNull Exception e) {
413+
result.error("Error performing getDocuments", e.getMessage(), null);
414+
}
415+
});
416+
break;
417+
}
390418
case "DocumentReference#setData":
391419
{
392420
Map<String, Object> arguments = call.arguments();

packages/cloud_firestore/ios/Classes/CloudFirestorePlugin.m

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,42 @@ - (FlutterError *)flutterError {
7878
return query;
7979
}
8080

81+
NSDictionary *parseQuerySnapshot(FIRQuerySnapshot *snapshot) {
82+
NSMutableArray *paths = [NSMutableArray array];
83+
NSMutableArray *documents = [NSMutableArray array];
84+
for (FIRDocumentSnapshot *document in snapshot.documents) {
85+
[paths addObject:document.reference.path];
86+
[documents addObject:document.data];
87+
}
88+
NSMutableArray *documentChanges = [NSMutableArray array];
89+
for (FIRDocumentChange *documentChange in snapshot.documentChanges) {
90+
NSString *type;
91+
switch (documentChange.type) {
92+
case FIRDocumentChangeTypeAdded:
93+
type = @"DocumentChangeType.added";
94+
break;
95+
case FIRDocumentChangeTypeModified:
96+
type = @"DocumentChangeType.modified";
97+
break;
98+
case FIRDocumentChangeTypeRemoved:
99+
type = @"DocumentChangeType.removed";
100+
break;
101+
}
102+
[documentChanges addObject:@{
103+
@"type" : type,
104+
@"document" : documentChange.document.data,
105+
@"path" : documentChange.document.reference.path,
106+
@"oldIndex" : [NSNumber numberWithInt:documentChange.oldIndex],
107+
@"newIndex" : [NSNumber numberWithInt:documentChange.newIndex],
108+
}];
109+
}
110+
return @{
111+
@"paths" : paths,
112+
@"documentChanges" : documentChanges,
113+
@"documents" : documents,
114+
};
115+
}
116+
81117
@interface FLTCloudFirestorePlugin ()
82118
@property(nonatomic, retain) FlutterMethodChannel *channel;
83119
@end
@@ -248,41 +284,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
248284
id<FIRListenerRegistration> listener = [query
249285
addSnapshotListener:^(FIRQuerySnapshot *_Nullable snapshot, NSError *_Nullable error) {
250286
if (error) result(error.flutterError);
251-
NSMutableArray *paths = [NSMutableArray array];
252-
NSMutableArray *documents = [NSMutableArray array];
253-
for (FIRDocumentSnapshot *document in snapshot.documents) {
254-
[paths addObject:document.reference.path];
255-
[documents addObject:document.data];
256-
}
257-
NSMutableArray *documentChanges = [NSMutableArray array];
258-
for (FIRDocumentChange *documentChange in snapshot.documentChanges) {
259-
NSString *type;
260-
switch (documentChange.type) {
261-
case FIRDocumentChangeTypeAdded:
262-
type = @"DocumentChangeType.added";
263-
break;
264-
case FIRDocumentChangeTypeModified:
265-
type = @"DocumentChangeType.modified";
266-
break;
267-
case FIRDocumentChangeTypeRemoved:
268-
type = @"DocumentChangeType.removed";
269-
break;
270-
}
271-
[documentChanges addObject:@{
272-
@"type" : type,
273-
@"document" : documentChange.document.data,
274-
@"path" : documentChange.document.reference.path,
275-
@"oldIndex" : [NSNumber numberWithInt:documentChange.oldIndex],
276-
@"newIndex" : [NSNumber numberWithInt:documentChange.newIndex],
277-
}];
278-
}
279-
[self.channel invokeMethod:@"QuerySnapshot"
280-
arguments:@{
281-
@"handle" : handle,
282-
@"paths" : paths,
283-
@"documents" : documents,
284-
@"documentChanges" : documentChanges
285-
}];
287+
NSMutableDictionary *arguments = [parseQuerySnapshot(snapshot) mutableCopy];
288+
[arguments setObject:handle forKey:@"handle"];
289+
[self.channel invokeMethod:@"QuerySnapshot" arguments:arguments];
286290
}];
287291
_listeners[handle] = listener;
288292
result(handle);
@@ -302,6 +306,20 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result
302306
}];
303307
_listeners[handle] = listener;
304308
result(handle);
309+
} else if ([@"Query#getDocuments" isEqualToString:call.method]) {
310+
FIRQuery *query;
311+
@try {
312+
query = getQuery(call.arguments);
313+
} @catch (NSException *exception) {
314+
result([FlutterError errorWithCode:@"invalid_query"
315+
message:[exception name]
316+
details:[exception reason]]);
317+
}
318+
[query getDocumentsWithCompletion:^(FIRQuerySnapshot *_Nullable snapshot,
319+
NSError *_Nullable error) {
320+
if (error) result(error.flutterError);
321+
result(parseQuerySnapshot(snapshot));
322+
}];
305323
} else if ([@"Query#removeListener" isEqualToString:call.method]) {
306324
NSNumber *handle = call.arguments[@"handle"];
307325
[[_listeners objectForKey:handle] remove];

packages/cloud_firestore/lib/src/query.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,18 @@ class Query {
7979
return controller.stream;
8080
}
8181

82+
/// Fetch the documents for this query
83+
Future<QuerySnapshot> getDocuments() async {
84+
final Map<String, dynamic> data = await Firestore.channel.invokeMethod(
85+
'Query#getDocuments',
86+
<String, dynamic>{
87+
'path': path,
88+
'parameters': _parameters,
89+
},
90+
);
91+
return new QuerySnapshot._(data, _firestore);
92+
}
93+
8294
/// Obtains a CollectionReference corresponding to this query's location.
8395
CollectionReference reference() =>
8496
new CollectionReference._(_firestore, _pathComponents);

packages/cloud_firestore/test/cloud_firestore_test.dart

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,19 @@ void main() {
6363
(_) {},
6464
);
6565
return handle;
66+
case 'Query#getDocuments':
67+
return <String, dynamic>{
68+
'paths': <String>["${methodCall.arguments['path']}/0"],
69+
'documents': <dynamic>[kMockDocumentSnapshotData],
70+
'documentChanges': <dynamic>[
71+
<String, dynamic>{
72+
'oldIndex': -1,
73+
'newIndex': 0,
74+
'type': 'DocumentChangeType.added',
75+
'document': kMockDocumentSnapshotData,
76+
},
77+
],
78+
};
6679
case 'DocumentReference#setData':
6780
return true;
6881
case 'DocumentReference#get':
@@ -407,5 +420,32 @@ void main() {
407420
expect(colRef.path, 'foo/bar/baz');
408421
});
409422
});
423+
424+
group('Query', () {
425+
test('getDocuments', () async {
426+
final QuerySnapshot snapshot = await collectionReference.getDocuments();
427+
final DocumentSnapshot document = snapshot.documents.first;
428+
expect(
429+
log,
430+
equals(
431+
<Matcher>[
432+
isMethodCall(
433+
'Query#getDocuments',
434+
arguments: <String, dynamic>{
435+
'path': 'foo',
436+
'parameters': <String, dynamic>{
437+
'where': <List<dynamic>>[],
438+
'orderBy': <List<dynamic>>[],
439+
},
440+
},
441+
),
442+
],
443+
),
444+
);
445+
expect(document.documentID, equals('0'));
446+
expect(document.reference.path, equals('foo/0'));
447+
expect(document.data, equals(kMockDocumentSnapshotData));
448+
});
449+
});
410450
});
411451
}

0 commit comments

Comments
 (0)