Get all documents from collection in firestore - firebase

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.

Related

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: Identify if there are documents in a firebase collection

I want to post data to a series of collections and documents one within the other,
CollectionReference data = FirebaseFirestore.instance
.collection('Data')
.doc(user)
.collection('First')
.doc(category)
.collection(time);
data.add({'element': 'field'});
but when I try to do it, the names of the dynamic names appear in italics, it would not be a problem if it were only a variation of the font style, the problem is that when I try to know if there is data in the collection First it shows me that there is nothing
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Data')
.doc(user)
.collection('First')
.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData) {
print(snapshot.data);
return Icon(Icons.check);
}
return Icon(Icons.error);
},
);
}
flutter: null
It is necessary to separate by first, second, third, etc and each of these must have separate different categories and in each category must have its time
Firebase looks like this
Data -> S6W4kb1dKycD060v47FFs0i528Q2 -> First -> post -> 19:00
Only if I add an item directly from the Firebase console does it recognize that items exist
In your call fragment...
CollectionReference data = FirebaseFirestore.instance
.collection('Data')
.doc(user)
.collection('First')
.doc(category)
.collection(time);
...NONE of the .collection() and .doc() create anything - they are just extending the refPath of the underlying reference i.e. Data/{user}/First/{category}/time is the collection you will add to. When you FINALLY execute data.add({'element': 'field'}) a SINGLE document with contents (and unspecified Id) {'element': 'field'} is added.
It is helpful to remember that in Firestore, "collections" are not a physical identity; they are a convenient part of a structured path to a document. For example, in
TopLevel/document1/NextLevel/document2/NextNextLevel/document3/NextNextNextLevel/actualDocument
NONE OF TopLevel, document1, NextLevel, document2, NextNextLevel, document3, or NextNextNextLevel need to exist - which is why they show in italics in the console.

how can i get firestore collection and subcollection in flutter

Thank you for reading my question.
My English may not be good enough before I ask you a question.
this my firestore structure
I'm using a flutter and I have to bring the product collection and subcollection image together from the FireStore.
I succeeded get data, but I don't know how to use it as a streambuilder.
FirebaseFirestore.instance
.collection("products")
.get()
.then((value) async => {
for (DocumentSnapshot document in value.docs)
{
log(document.data().toString()),
await document.reference
.collection("images")
.get()
.then((value) => {
for (DocumentSnapshot document
in value.docs)
{
log(document.data().toString()),
}
}),
}
});
code run log result
I looked for it for three days, but I couldn't find the answer.
Please reply.
Have a nice day. Thank you.
The only way I have found to do this is to use 2 different streambuilders, naming each snapshot differently. Use one for the products collection, then images for the other. What I would recommend is to add a field of 'images' in your product document and make it an array of string types. This will allow you to reference the images straight from each product document

Cloud firestore read count in StreamBuilder

Firebase structure:
Code:
I'm using a StreamBuilder for document uid like this:
#override
Widget build(BuildContext context) {
return StreamBuilder<User>(
stream: _stream(),
builder: (BuildContext _, AsyncSnapshot<User> snapshot) {
// this block may get called several times because of `build` function
if (snapshot.hasData) {
final user = snapshot.data;
return SomeWidget(user: user);
}
return CircularProgressIndicator();
},
);
}
Questions:
Since StreamBuilder's builder may get called several times because of the build() method, will that cost me a read every time builder gets called?
Is there any difference in terms of read-count when reading complete uid vs reading uid/education?
If I update age and name value, will that count as one-write or two-writes in terms of firebase write-count?
Firestore charges on every document read, write and delete therefore:
Since StreamBuilder's builder may get called several times because of the build() method, will that cost me a read every time builder gets called?
Yes, if you are reading(retrieving) one document each time, then you will be charged as one read.
Is there any difference in terms of read-count when reading complete uid vs reading uid/education
No difference. The read is done in the document, when you retrieve one document then you are doing one read.
If I update age and name value, will that count as one-write or two-writes in terms of firebase write-count?
If you update one document once (even if all the fields are updated), it will cost you one write operation.

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