how to delete document by field inside collection inside document inside collection on firestore - flutter

I have Doctor collection when each doctor (represent by his email ) has a collection called patients_waiting.
Now, what I'm trying to do is delete one document from the paitents_waiting collection by field calls patients containing his email.
but I tried many solutions and none of them works for me now.
what I have tried to do :
Firestore.instance
.collection("Doctors")
.document(doctorEmail)
.collection("paitents_waiting")
.document(paitentEmail)
.delete();
now it's not good because the document is saved in uid and not by email but I tried to play with the where function but with no success.
how do I found this document by email and delete him?
I will mention that I'm doing it on flutter, but I think it doesn't matter.

as long as you have the patient's email address you can search with and delete it
Firestore.instance
.collection("Doctors")
. document(doctorEmail)
.collection("paitents_waiting")
.where('patient', isEqualTo:paitentEmail )
.get().then((value) => value.docs.single.reference.delete())
Nb: you are using an old version of firestore

Inside your paitents_waiting collection, the documents are NOT named according to patient email, they are randomly generated Firebase IDs. Take a closer look.
Firestore.instance
.collection("Doctors")
.document(doctorEmail)
.collection("paitents_waiting")
.document(paitentEmail) //this in your Firebase isn't an email, it's "xaErf43Asd..etc"
.delete();
If you want to follow this approach, which should be working otherwise, when you want to create a patient waiting document, use .set instead of .add, and set the document id to your pateint's email, like this:
Firestore.instance
.collection("Doctors")
.document(doctorEmail)
.collection("paitents_waiting")
.document(paitentEmail)
.set({your patient data here});
This should get things working for you.

To delete all patients for a doctor by the email you can use a combination of Firestore query and batch updates. The first one we need to get all patients with the same email and the other to delete them. A function for that would look like this:
Future<void> deletePatiensForDoctor(String docEmail, String patEmail) async {
WriteBatch batch = FirebaseFirestore.instance.batch();
QuerySnapshot querySnapshot = await Firestore.instance
.collection("Doctors")
.document(docEmail)
.collection("paitents_waiting")
.where('email', isEqualTo: patEmail)
.get();
querySnapshot.docs.forEach((doc) {
batch.delete(doc.reference);
});
return batch.commit();
}

Related

I want to get documents IDs from specific collection in firebase firestore

I have flutter app with firebase firestore in firestore I have on collection inside the collection there is few documents I want to get these documents IDs and put them in list<Strings> to use them in listview.seperated so I can click on one Item and move to another page where I can find the fields of specefic documents but I can't achieve that is there anyway to do that thanks
I try every thing to get the documents Id but nothing work with me I am new to flutter and firebase please help thanks
use doc.id to get ID of document:
List<String> iDs = [];
FirebaseFirestore.instance
.collection('buying2')
.get()
.then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
print(doc.id); //this is document ID
iDs.add(doc.id);
});
});

Can't get one document from flutter cloud firestore

I'm trying to get one document by user id from firebase cloud firestore using flutter.
I tried firstly to fetch the data then added a condition to it, but i'm not able to display the data or even print it in the console!
Here is what i've tried so far:
database.dart:
Future<DocumentSnapshot?> getFileByUser(String userId) async {
return FirebaseFirestore.instance
.collection('cartesPro')
.where('cartUserId', isEqualTo: FirebaseAuth.instance.currentUser!.uid)
.get()
.then((value) {
value.docs.forEach((element) {
print(element.id);
});
});
}
ui page:
User? user = FirebaseAuth.instance.currentUser;
showFile() {
final files = DatabaseMethods().getFileByUser(user!.uid);
print(files);
}
and then made the call in a button so I can print the result only! it's returning the documents of the actual user, but I couldn't map the result in order to get the latest in timestamp order!
I appreciate any kind of help, thanks in advance!
If you want to get the most recent document for the user, you should order on the field that has the timestamp and the limit to a single result:
FirebaseFirestore.instance
.collection('cartesPro')
.where('cartUserId', isEqualTo: FirebaseAuth.instance.currentUser!.uid)
.orderBy('timestamp', descending: true)
.limit(1)
.get()
See the Firestore documentation on ordering and limiting data for more on this.

Using fields in a document for another query

I have 2 collections, one called Timeline and one called Posts. The first one is very simple, having 2 fields: 'PostId' and 'OwnerId', while the second one is a little bit more complex but it is not important for the purpose of my question.
Using 'OwnerId' and 'PostId' I can get a specified post in the collection Posts.
What I want to do is getting all the docs in timeline of a specified user, for each doc use it to get the post infos in Posts collection, and order the posts in descending timestamp, but I can't find a smart and effective way to do so.
To get all the docs of a specified user in Timeline I write:
QuerySnapshot snapshot = await timelineRef
.doc(currentUserID)
.collection('timelinePosts')
.get();
And to get a specified post from Posts collection I write:
QuerySnapshot snapshot = await postsRef
.doc(ownerId)
.collection('userPosts')
.doc(postId)
.get();
How can I mix these two to get the result I want? Thank you
There is no concept of a server-side join in Firestore, nor is there a way to filter the documents returned based on information in documents in another collection. All Firestore queries can do is evaluate the literal data in the candidate documents (through an index) and filter based on that.
So you will either have to duplicate the data to filter on in each userPosts document, or perform a so-called client-side join - with the latter being the most reasonable option for this use-case as far as I can see.
You'll end up with individual get() calls for the documents, or a bunch in in queries on the FieldPath.documentId() you get from timelinePosts, and then merge the results in your application code.
At the moment I found a solution that is not very elegant but at least is working:
QuerySnapshot snapshot = await timelineRef
.doc(widget.currentUser.userID)
.collection('timelinePosts')
.orderBy('timestamp', descending: true)
.get();
List<TimelineItem> timelineItems =
snapshot.docs.map((doc) => TimelineItem.fromDocument(doc)).toList();
List<PostWidget> postsTemp = [];
for (var element in timelineItems) {
DocumentSnapshot documentSnapshot = await postsRef
.doc(element.ownerId)
.collection('userPosts')
.doc(element.postId)
.get();
postsTemp.add(PostWidget(Post.fromDocument(documentSnapshot)));
}
I added timestamp field to my timelinePosts, created a class to contain the data from the first query, and then I did a second query based on the parameters I got on the first one for each doc.
Hopefully I'll find a more efficient solution but at the moment I use this

How to update a Firestore document after querying in Flutter

I am trying to figure out how to update my document after I query the one I want to update. Here is the code I came up with:
Firestore.instance.collection("Social_Posts").where(data["postTitle"], isEqualTo: "postTitle").where(data["postContent"], isEqualTo: "postContent")
.snapshots()
.listen((event) {print("hh");});
Whenever I perform this query to find the correct document, I would like to update the document by adding a number to it.
It is possible to update the document from inside, The easier way to do that would definitely be to use the documentID and to increment the value Firestore has a special property, FieldValue.increment(1). Using this you can easily increment a field.
Lets say the field in the document you want to increment by 1, is "numberField".
Updated code using async/await style:
onTap: () async {
setState(() {
_title = data["postTitle"];
_content= data["postContent"];
});
print(_title);
print(_content);
QuerySnaphot snapshot = await Firestore.instance.collection("Social_Posts")
.where("postTitle" , isEqualTo: _title)
.where("postContent", isEqualTo: _content)
.getDocuments();
if(snapshot.documents.isNotEmpty)
{
snapshot.documents.forEach((doc){
doc.reference.updateData({"views" : FieldValue.increment(1),});
});
}
}
The numberField will be incremented without needing to make an extra call to know the present value.
EDIT : You were making a mistake in the .where() method
You can do that by using the document id you quired from inside the listen function in your case by using the event.documents[0].documentID assuming that your query returns one document only and then you can call the updateData method from Firestone package
Your code might looks like this:
Firestore.instance.collection("Social_Posts")
.where(data["postTitle"], isEqualTo: "postTitle")
.where(data["postContent"], isEqualTo: "postContent")
.snapshots()
.listen((event) {
Firestore.instance
.collection("Social_Posts")
.document(
event.documents[0].documentID)
.updateData(
updateEvent) //Add here the new object you want to
.whenComplete(() {
// You can add your desire action after the row is updated
}
});
You can check package page for more information https://pub.dev/packages/cloud_firestore
And if you want to check a sample on how to perform CRUD functionalities you can check this repository: https://github.com/sayed3li97/flutter_firestore_crud

CollectionReference to DocumentReference

I'm trying to perform a firestore transaction in Flutter.
Therefore I need to pass the documentReference.
There is no problem, when accessing the "lesson" document based on the identifier.
The issue is when fetching the active user pass. The where I'm trying to use returns the Query, and the .reference() returns the CollectionReference (which is not accepted by the transaction method).
How can I get the reference to the document basing on the value of its field.
To spice it up: DB rules don't allow me to read ALL the passes. I've got only access to those, that have my UserID (double checked - working).
DocumentReference lessonRef =
await _db.collection('lessons').document(lesson.identifier);
CollectionReference passRef = await _db
.collection('passes')
.where('userID', isEqualTo: user.identifier).reference();
You can get the DocumentReference of the Queried documents like so:
Firestore.instance
.collection('passes')
.where('userID', isEqualTo: user.identifier)
.snapshots()
.listen((reference) =>
data.documents.forEach((doc) => /*do what you want with doc.reference*/));
(I'm not an expert in Flutter and I could't test the code, but I based the answer in the API reference)