Reputation: 708
I have a collection called UserCollection
,
into this collection I have a subcollection with other specific documents called 'UserSubCollection'
with StreamBuilder I am trying to get these collections unsuccesfully
StreamBuilder(
stream: FirebaseFirestore.instance
.collection('UserCollection')
.doc(firebaseUser.uid).collection('UserSubCollection')
.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError)
return Center(child: Text("Error"));
else if (snapshot.data.docs.isEmpty) //also check if empty! show loader?
return Center(child: Text('Errors'));
else
return new ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (BuildContext context, int index) {
I am able to get just one or a collection or the subcollection. there is a way to get them both?
Upvotes: 0
Views: 782
Reputation: 2215
First question: do your items need to update automatically over time? Otherwise, I suggest you a FutureBuilder instead of a StreamBuilder.
To get both I suggest you using a separate method like this:
Future<List</*INSERT RETURN TYPE*/>> _retrieveUsers() async{
//get all the users
QuerySnapshot query = await FirebaseFirestore.instance
.collection('UserCollection').get();
Map<String,Map<String,dynamic>> userMap = Map();
//add each user to the map
query.docs.forEach(doc => userMap.putIfAbsent(doc.id, doc.data());
FutureGroup<QuerySnapshot> queries = FutureGroup(); //add async package in pubspec.yaml [there might be version issues]
//retrieve sub collections and bind them to the corresponding user
query.docs.forEach((doc) => queries.add(_retrieveSubCollection(userMap,doc)));
//Close queries
queries.close();
//Await for all the queries to be completed
await queries.future;
//now you have for each user a structure containing its data plus everything in its sub collection. Do whatever you want and then return a list or a map according to what you need
return /*YOUR RETURN*/;
}
Future<Void> _retrieveSubCollection( Map<String,Map<String,dynamic>> userMap, DocumentSnapshot doc) async{
//retrieve the subcollection of a document using its id
QuerySnapshot query = query FirebaseFirestore.instance
.collection('UserCollection')
.doc(doc.id).collection('UserSubCollection').get();
//bind the subcollection to the relative user
Map<String,dynamic> userData = userMap[doc.id];
userData.add("subcollection", query.docs.map((subDoc) =>subDoc.data()).toList());
userMap.update(doc.id,(value)=> userData);
return;
}
Now just use a future builder to display the result of your queries.
FutureBuilder(future: _retrieveUsers(), builder: (context,snapshot) {/*YOUR CODE*/}
I actually didn't try the code in a real environment, so if you find issues on updating the user map there might be problems due to asynchronous updates. However, since every query target a specific element in the map, I don't think there will be issues
Upvotes: 1