how to get data from firestore sub-collection - firebase

i have a firestore database in which i have "Singer" then inside every singer there is a sub-collection of "Song List" for every singer. i am able to get data from main collection but not from sub-collection. can you guys help?
stream Builder
StreamBuilder(
stream: Firestore.instance.collection('singers').snapshots(),
ListView.Builder
ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) => SingleChildScrollView(
this is where i want to show data from sub-collection
Text(
snapshot.data.documents[index]['name'],
style: TextStyle(
fontSize: 20, color: Colors.red[500]),
)
Database

You can get the data from the collection by accessing the subcollection inside the document like this
Firestore.instance.collection('singers').document('aryana sayeed').collection('song list').snapshots()
or
Firestore.instance.collection('singers/aryana sayeed/song list').snapshots()

You can read it like this:
Firestore.instance.collection('singers').snapshot().listen((val)=>{
val.documents.forEach((doc)=>{
doc.reference.collection('song list')
.getDocuments().then((res)=>{
res.douments.forEach((d)=>{
print(d.data);
})
})
})
});
Now this gives you a stream to all docs of collection singers and thier subcollection

To clarify what you are saying: you want a list of all the songs from all the singers,
Easy-Peasy. CollectionGroup is your friend.
I don't use your environment, but I can see that:
StreamBuilder(
stream: Firestore.instance.collectionGroup('song list').snapshots(),
is the start you need. collectionGroup treats all sub-collections with the name 'song list' as one collection.
NOTE (because this always comes up)
Each documentSnapshot returned include a field 'refpath' - which is a string with the entire path to that specific document. You can trivially parse the string to find the parent document(s) or collections(s). For example, a particular song with have in it's refPath ".../singers/{singerID}/songlist/{songID}"
btw, I HIGHLY HIGHLY HIGHLY recommend AGAINST using the singer name as the document ID. Queries are generally of fields, not documentID's, so it won't help your code find the artist, and they are neither unique enough nor randomly distributed enough to be efficient. Let Firestore generate unique documentID's for you, and put the artist name in a field.

Related

How can i show images to limited users in flutter

I want to show my post to my followers only how can I implement that here is my code.
here is the structure of my user collection
here is the collection of posts by user
final model.User userProvider = Provider.of<UserProvider>(context).getUser;
StreamBuilder(
stream: FirebaseFirestore.instance
.collection(post_collection)
.orderBy("datePublished",
descending:
true)
.snapshots(),
builder: (context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
return ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) =>
PostCard(snap: snapshot.data.docs[index].data()));
}),
My logic to approach this problem would be:
If I am a user, I should be able to see the post of people I follow, so the source of posts that are visible to me would arrive only from the list of people I follow. Create this list as an attribute of users in their database record. Every time the user follows someone, that someone is added to this list.
So if you want your posts to be seen only by your followers, as soon as someone follows you, your account would be added to the list of people they follow. Thus your account becomes just another source of accounts from which that particular follower receives post updates from.
You could implement the logic to receive posts only from the list of people a particular user follows. This way only your followers will be able to see your posts.

How to get subcollection data from firebase?

Im trying to calculating some data together . What I have is a videos collection and then each video has a doc id and and then some field for example the uid of the user that uploads this video. And also every video has a sub collection named uservotes. Inside their I saved user voting of this video. This is how It looks
And what I want is getting of one user the user votes rating field calculating together .
HERes how I get for one video the rating maybe that will help to understand
FutureBuilder(
future: firebase,
builder:
(BuildContext context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Center(
child: Text("loading..."));
} else {
double summe = 0.0;
final docs = snapshot.data.docs;
for (int i = 0;
i < docs.length;
i++) {
summe += (docs[i]['rating']);
print(summe);
}
final possiblestars = docs.length * 5;
print(possiblestars);
return Text(
"${summe.toInt()}/${possiblestars}",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18),
);
}
}),
The firebase stream is this one
var firebase = FirebaseFirestore.instance
.collection('videos')
.doc(videos.data()['id'])
.collection('uservotes')
.get();
So instead of getting all user votes of one video I wanna get all uservotes of all videos form the same user. You can see that each video in videos collection has uid field and thats the uid of the user that upload the video I can get the current user id with that
final uid= FirebaseAuth.instance.currentUser.uid;
And every video that has saved this uid as uid value Iinside field "uid" in videoscollction is one off the videos that I needed
. Then I wanna get of each video the sub collection uservotes all rating to calculating they together . Dont get confused about the same uid doc inside user votes collection thats because the user that uploads this current video also rate his own video .
Hope anyone can help .
For your requirement, with your data model, you would need to query all the videos docs with the same uid, and then, for each doc, query all the doc of the uservotes subcollection.
You could simplify this queries by adding the video owner uid to the uservotes docs and use a collectionGroup query.
HOWEVER, it is not recommended at all to query an entire (sub)collection each time you want to get the number of documents, because you are billed for each document that you read. So it can very fast generate an important bill...
You should maintain a counter for each user (and maybe for each video?). For that the best is to use distributed counters. I would advise to use Cloud Functions to update the counters, this way end-users cannot modify the counters.
Unfortunately, it's impossible in a single query. You should get all videos firstly and then make a new call for each one to get subcollection.

Flutter Firebase Cloud Firestore How to filter a stream with where() query using a subcollection

So i have in my Cloud Firestore I have a collection of recipes that contains documents(with casual ids) with different recipes. Every document has a 2 fields with the recipe name and the recipe duration.
Every document has also a collection named likedBy where there is documents that have as ids user ids and have a single field with the date of the like.
Now i want to return all recipes that have in their likedBy subCollection the userId.
i' ll write what i' ve tried with only essential code.
String userId= 'uiuu4fn3fff4fu';
Scaffold(
body:StreamBuilder(
stream: THE STREAM THAT I NEED,
builder:(context,snapshot){
return ListView.builder(
itemCount: snapshot.data.documents.length
itemBuilder:(context,index){
return Column(children:[
Text(snapshot.data.documents[index]['recipeName']),
Text(snapshot.data.documents[index][recipeDuration]),]) } ) } ) )
What i want is to return only documents that have in their likedBy subCollection a specific user uid.
I' ve tried with this stream
Firestore.instance.collection('recipes').parent().collection('likedBy').where(FieldPath.documentId,
isEqualTo,userId).snapshots()
But it doesn' t work and i have no idea what else i can try.
Any help is highly apprecieted.
Items should not be added by the users but by admins, that means that there will be a list of items added by admins and a list of users that can add them in favorites and what i want to achieve is that users can see all their favorites in the order in which they saved them. To be clear i want something like Instagram functionality to save posts.
So you want a way to query subcollection. To do that simply use collectionGroup method:
db.collectionGroup('likedBy').where('userId', '==', '1');
To order by a value use timestamp:
// add to your document
db.collection("items")
.add({...item, created: firebase.firestore.Timestamp.fromDate(new Date()) })
and to orderby this value use orderby:
db.collection("items")
.orderBy("created", "asc")
What you might want to do instead is have a 'likedBy' property on the recipe document instead of its own sub-collection. If it is just a list of userids that should be no problem. Then you can just say recipeCollection.where(likedBy, array contains: userId)

Get all documents from collection in firestore

I'm trying to get all posts from my 'instagram' clone app. This is the path I have in firestore: posts > (unique ownerId) > userPosts > (unique postId)
How can I retrieve all posts using a stream builder? I tried doing so with
body:
StreamBuilder<QuerySnapshot>(
stream: postsRef.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return circularProgress();
}
List<Post> posts = snapshot.data.documents.map((doc) => Post.fromDocument(doc)).toList();
return ListView(children: posts);
},
)
I want to display only the posts' pictures in a stack of cards.
You can't use wildcards with listeners in Cloud Firestore. You need to name the specific document and collections in the path. So, if your (unique ownerId) is unknown at the time of the query, you will not be able to know anything about the documents changing in its subcollections.
As an alternative, on a backend you control, you can list subcollections of a document, then query those documents. Or, you can use a Cloud Functions trigger and notify interested client apps (maybe with Cloud Messaging) as changes happen.

Flutter Firestore Two StreamBuilders of the Same Document Count as 2 Reads?

In my Flutter app, will it count as two reads from Firestore if I have two nested StreamBuilders reading from the same document? Or is it cached in a way that it will only count as one read?
Here's an example of what I'm talking about.
StreamBuilder(
stream: Firestore.instance.document(path).snapshots(),
builder: (context, asnap){
//Some nested widgets...
return StreamBuilder(
stream: Firestore.instance.document(path).snapshots(),
builder: (context, asnap){
return MyWidget();
},
);
},
);
As far as I know, the Firestore client deduplicates these listeners. So if a first listener is already active for the exact same data, it won't attach a second listener. So you won't be charged for two reads, but (possibly even more important to your users) the data will only be transferred once.

Resources