Flutter: Identify if there are documents in a firebase collection - firebase

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.

Related

Flutter Cloud Firestore isLessThan Filter not Working with two .where() Statements

I'm displaying a list of documents in a Cloud Firestore collection using a StreamBuilder. Currently, I'm able to use a .where() statement to filter this list of documents by title (a string), but I want to add another .where() statement to filter by price (a number). I want the app to only display a list of documents that have titles equal to a certain string and have prices less than a certain number. The filtering by titles works fine, but the issue is with the isLessThan operator when adding the second .where() statement.
Current code (one .where() statement):
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("ads")
.where('title', isEqualTo: "Car")
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Text(
"Loading...");
} else {
return //Rest of the code isn't relevant
}
},
),
The code I want to work with two .where() statements (it just returns the loading text, meaning the snapshot doesn't have any data):
StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance
.collection("ads")
.where('title', isEqualTo: "Car")
.where('price', isLessThan: 12000.0) //This line is new
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Text(
"Loading...");
} else {
return //Rest of the code isn't relevant
}
},
),
I can't decide if this is an issue with the fact that there are two .where() statements or if it's an issue with the isLessThan operator. Removing the first .where() statement (the one about titles) and keeping the second one about prices filters the documents by price correctly (theoretically making the issue the fact that there are 2 .where() statements). However, changing the isLessThan in the second .where() statement to isEqualTo and then changing the 12000.0 to a price I know exists in the list of documents (while keeping the first .where() statement) works. This makes me think that it's an issue with combining the isLessThan operator and a second .where() statement.
Note: all price values in the Firestore collection are doubles (the data type in Cloud Firestore is set to "number" and they all have decimals - e.g. 1.0 instead of 1).

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.

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.

How to retrieve 1 document from firebase/firestore collection based on date in dart/flutter?

Ofc, I know the basic way we retrieve a whole bunch of documents from a collection like so:
stream: Firestore.instance
.collection("collection_name")
.orderBy("date", descending: true) // new entries first
.snapshots(),
builder: (context, snapshot) { ....
This is fine when I'm displaying a whole bunch of data.
But I have situation where I need to do some calculations with the last added numbers, meaning I just need to get 1 document, so I what I do is sort data by date and limit by 1, then make the query for this one document like this
List<DocumentSnapshot> list;
QuerySnapshot querySnapshots;
if (await AuthHelper.checkIfUserIsLoggedIn()) {
String userId = await AuthHelper.getUserID();
querySnapshots = await Firestore.instance
.collection("collection_name")
.orderBy("date", descending: true) // new entries first, date is one the entries btw
.limit(1)
.getDocuments(); // Get Documents not as a stream
list = querySnapshots.documents; // Make snapshots into a list
return (list ?? null);
} else {
return null;
}
But is this the best way to do it ? When making this query aren't I getting the whole set of documents and discarding the rest ? Which means when this collections grows this is going get slower and slower ?
Is there a better way to retrieve the last added document ? So I can use it as list/array/map and not as stream ?
Thanks.
When you limit the query, you are only ever going to read that number of documents maximum. It's not going to read the entire collection and discard the extras.

Resources