How to calculate read/writes on Firestore operation? - flutter

I already know that having a direct path to a document id would result in a single read from the firestore through using the get() function. I am trying to retrieve a document fields value so I use FirebaseFirestore.instance.collection('users').doc(userUid).get() to get the documentSnapshot, then use await _userCollection.then((value) => value.get("field name")) to get the document field value. I do this to get "n" fields.
So, my question is would the second get() ,used to retrieve each document field, be calculated in the read costs or is it only the get() ,used to retrieve the documentSnapshot itself, which should be calculated.
Here is my full code:
_setStoreOwnerObjByFetchingUserData(String userUid) async {
Future<DocumentSnapshot<Map<String, dynamic>>> _userCollection =
FirebaseFirestore.instance.collection('users').doc(userUid).get();
await StoreOwner().updateOwnerData(
userUid,
await _userCollection.then((value) => value.get("shopName")),
await _userCollection.then((value) => value.get("shopAddress")),
await _userCollection.then((value) => value.get("shopType")),
await _userCollection.then((value) => value.get("shopSize")),
await _userCollection.then((value) => value.get("ownerName")),
await _userCollection.then((value) => value.get("ownerNumber")),
await _userCollection.then((value) => value.get("subscriptionStatus")));
}

Would the second get() ,used to retrieve each document field, be
calculated in the read costs or is it only the get() ,used to retrieve
the documentSnapshot itself, which should be calculated.
You only pay for the "get() used to retrieve the DocumentSnapshot". Once the asynchronous get() operation is complete the DocumentSnapshot is in memory in your app and you can call its get() method as many times as you want without any Firestore based cost.
THEREFORE it appears that in your code you query several times the database when it is not necessary. You should adapt it as follows:
_setStoreOwnerObjByFetchingUserData(String userUid) async {
Future<DocumentSnapshot<Map<String, dynamic>>> _userCollection =
FirebaseFirestore.instance.collection('users').doc(userUid).get();
var docSnapshot = await _userCollection;
await StoreOwner().updateOwnerData(
userUid,
docSnapshot.get("shopName"),
docSnapshot.get("shopAddress"),
//...
}

Related

How to delete data from Firestore with specific parameter flutter?

I'm trying to delete some data with where parameter to specify which one should be deleted.
I've this method and it works perfectly.
final FirebaseFirestore _db = FirebaseFirestore.instance;
Future deleteInstructorDocumentInFirestore(String url) async {
_db.collection(instructorsDocument)
.where("photo", isEqualTo: url)
.get()
.then((value) {
for (var element in value.docs) {
_db.collection(instructorsDocument)
.doc(element.id)
.delete();
}
});
}
So I've tried the same thing with this one but it doesn't work.
Firestore
Function
final FirebaseFirestore _db = FirebaseFirestore.instance;
Future deleteEvent(String uid, DateTime from, DateTime to) async {
print("From: $from");
print("From type: ${from.runtimeType}");
print("To: $to");
print("To type: ${to.runtimeType}");
_db.collection(instructorsEvent)
.where("uid", isEqualTo: uid)
.where("from", isEqualTo: from)
.where("to", isEqualTo: to)
.get()
.then((value) {
for (var element in value.docs) {
_db.collection(instructorsEvent)
.doc(element.id)
.delete();
}
});
}
What am I doing wrong.
Thanks in advance
The from and to fields are strings. But you are trying to compare them to dart DateTime object, which are not strings. As such, they will not match in any query - your queries are simply returning no documents at all, so there is nothing to delete. (I suggest adding some debug logging to better observe this for yourself.)
Firestore will not convert DateTime objects to strings for you, nor will it try to guess how to compare them for you. You must provide a similar type of value to the document field you are trying to compare to.
So, if your document fields must remain strings, then you should find a way to convert your DateTime objects to strings before handing them to a Firestore query. Or, you must find another way of representing points in time (in Firestore, usually a timestamp type field), then provide objects to the query that Firestore naturally understand to be comparable to timestamps.
See also:
Flutter: query Firestore document by timestamp
How to query for an entire day with timestamp values in Firestore
Problem Solved
#Doug Stevenson thanks
Utils
static String toDateTimeToStringFromFirestore(DateTime dateTime) {
final date = DateFormat("yyyy-MM-ddTHH:mm:ss.SSS").format(dateTime);
return date;
}
EventViewModel
Future deleteEvent(String uid, DateTime from, DateTime to) async {
final fromString = Utils.toDateTimeToStringFromFirestore(from);
final toString = Utils.toDateTimeToStringFromFirestore(to);
_db.collection(instructorsEvent)
.where("uid", isEqualTo: uid)
.where("from", isEqualTo: fromString)
.where("to", isEqualTo: toString)
.get()
.then((value) {
for (var element in value.docs) {
_db.collection(instructorsEvent)
.doc(element.id)
.delete();
}
});
}

Saving document from Firestore database in Flutter

I am trying to get a document from the database where the users can put in an email and it will pull the document and save it so I can use the document in an editing module. Here is my readUsers method
Future ReadUserinDatabase(String email) async {
Stream<List<DatabaseUser>> User = FirebaseFirestore.instance
.collection('Users')
.where('Email' == email)
.snapshots()
.map((snapshot) => snapshot.docs
.map((doc) => DatabaseUser.fromJson(doc.data()))
.toList());
print(User.map);
}
I will be grabbing the document ID from the returned document so I can put it in for doc to edit
Future EditUserinDatabase(
String oldemail, String newemail, String oldrole, String newrole) async {
final docUser = FirebaseFirestore.instance.collection('TEST').doc('Doc ID goes Here');
await docUser.update({'Email': newemail, 'Role': newrole});
}
The error that is occurring is when I print User.map it is not printing the information in the document it is printing '$user' and is not saving in a form I can use it. How do I save the document

Firebase Reference

How can I reference the collection in the document I auto-id in Firebase?
final CollectionReference _olanaklar5 = _database
.collection("Kategoriler")
.doc("Hoteller")
.collection("5_Yıldızlı")
.doc() //======> here
.collection("Olanaklar");
You can get list all document id with doc.id
List<String> _listDocId = [];
await fireStore
.collection("Kategoriler")
.doc("Hoteller")
.collection("5_Yıldızlı")
.get()
.then((QuerySnapshot querySnapshot) {
for (var doc in querySnapshot.docs) {
_listDocId.add(doc.id);
}
});
and query in list doc id
for (var id in _listDocId) {
final CollectionReference _olanaklar5 = _database
.collection("Kategoriler")
.doc("Hoteller")
.collection("5_Yıldızlı")
.doc(id)
.collection("Olanaklar");
}
If you're using Firebase auth, it's preferred to keep User's UID as doc, else you can use .where() as a query to match the fields in all documents. But as the app scales, it will be a hectic process and will consume many reads.

Unexpected text "return" inside function

int FriendsNum() {
_firestore.collection('Friends').doc(User.userID).collection("Friends").where("Status",isEqualTo: 2)
.get()
.then((res)=> return{res.size});
return 0;
}
I am basically trying to get the number of documents that are inside the collection that has the status of 2, and the value should be returned so it can be displayed for the user, what can be changed in the syntax to make this work? with many thanks!
You have to change your function return type to a Future and use the await keyword to get the result from the firestore collection as it is an asynchronous operation itself.
The updated code will be the following:
Future<int> FriendsNum() async {
final count = await _firestore
.collection('Friends')
.doc(User.userID)
.collection("Friends")
.where("Status",isEqualTo: 2)
.get()
.then((res) => res.size);
return count;
}

How to get data from nested collection in Flutter firestore?

I am using provider and Stream to fetch data from Firestore. so now i want to access the inner collection. but i am not able to fetch the data. How can i access myOrders collection.
this is the structure of firestore.
i tried this code to fetch but not worked for me.
//Store data into myOrders collection
Future myOrders(String image, String price) async {
final FirebaseUser user = await _auth.currentUser();
return await userData
.document(user.uid)
.collection('myOrders')
.document()
.setData({
'orderedImage': image,
'orderedPrice': price,
});
}
// get the data as snapshot
List<OrderedModel> myOrderSnapShot(QuerySnapshot snapshot) {
return snapshot.documents.map((doc) {
return OrderedModel(
orderedImage: doc.data['orderedImage'] ?? '',
orderedPrice: doc.data['orderedPrice']);
}).toList();
}
// get the snapshot as stream
Stream<List<OrderedModel>> get orderedStream {
return userData.document(uid).collection('myOrders').snapshots().map(myOrderSnapShot);
}```
did you try printing the values and debug the code?