Firestore: cant delete document - firebase

this is my function for deleting a document in my "files" collection
Future<void> deleteProgram(String id, String program) async {
try {
print(id + "----" + program);
await firestoreInstance.collection("files").doc(program).delete();
// await firestoreInstance.collection("programs").doc(id).delete();
print("done");
} catch (e) {
print(e);
}
}
program is the id of the document, when i use this nothing gets deleted, even if i hardcode the ID.
this is what my collection looks like:
as you can see, each document in the files collection also has a subcollection called files
what am i doing wrong here?

The only way to delete a collection is to delete each individual document from it. There is no atomic operation to delete a collection.
In your screenshot the opleiding4 is shown in italic, meaning that this document doesn't really exist, and the Firebase console merely shows that name to be able to show its files subcollection.
Once you delete all files from the /files/opeleiding4/files subcollection both that collection and its parent document will disappear from the Firebase console too.
Also see:
Firestore DB - documents shown in italics
How to recursively delete collection in firestore?
How to Delete all documents in collection in Firestore with Flutter

Related

Flutter Firestore update document name inside of collection

I am trying to add the ability to update the document name inside of my usernames collection inside my Flutter app. Here is my upload function:
Future<void> updateUsername() {
// Add a new user inside our the Usernames Collection. This is useful to check for username availablilty.
return usernames
.doc(username)
.set({
'uid': uid,
'timeCreated': DateTime.now(),
})
.then((value) => print("Username Added"))
.catchError((error) => print("Failed to add username: $error"));
}
Here is my database setup:
There is no option in firestore to rename a document. The way the most uses is to create a new document with the new name and the data that been in the old document, then delete the old document.
Take a look here: Can I change the name of a document in Firestore?
One more advice, if you're not going to put any data in the usernames documents, then make a document that has the name "usernames" and add them there, that would help to make less reads ... unless you know what you're doing.

Firebase and Kotlin: getting the id of a document issues

I have an interesting issue while playing with Firebase and Kotlin.
val docRef = db.collection("Year")
.document(DB_year.toString())
.collection("Month")
.document((DB_month+1).toString())
.collection("Day")
.document(today)
.collection("write")
.get()
.addOnSuccessListener { result ->
for(document in result) {
println("document_id : " + document.id)
}
}
If you get the document id with this code, you can get it normally.
enter image description here
enter code here
This code cannot get the document id.
val docRef = db.collection("Year")
.document(DB_year.toString())
.collection("Month")
.document((DB_month+1).toString())
.collection("Day")
.get()
Why is it like this?
my firestore collection
enter image description here
enter image description here
As shown in your Firebase console screenshot above, the documents in the Day collection are displayed with an italic font in the Firebase console: This is because these documents are only present (in the console) as "container" of one or more sub-collection but are not genuine documents.
If you create a document directly under the write collection with the full path Year/docYear1/Month/subDocMonth1/Day/subDcoDay1/write/writeDoc, no intermediate documents will be created (i.e. no document in the Month or Day collections).
The Firebase console shows this kind of "container" (or "placeholder") in italic in order to "materialize" the hierarchy and allow you to navigate to the write document but the Day document doesn't exist in the Firestore database. Hence the empty result for your second query
See this answer for more details.
Note that if you want to get the parent ids (docs and collections) for a doc in the write collection, you can use the parent properties of the DocumentReference and CollectionReference.
So you can do something like:
db.collection("Year")
.document(DB_year.toString())
.collection("Month")
.document((DB_month+1).toString())
.collection("Day")
.document(today)
.collection("write")
.get()
.addOnSuccessListener { result ->
for(document in result) {
println("Day_doc_id : " + document.reference.parent.parent?.id)
}
}

How to read firestore collection?

How can I list all documents in a firestore
FirebaseFirestore.instance
.collection('groups')
.doc('dialog')
.get()
.then((DocumentSnapshot documentSnapshot) {
if (documentSnapshot.exists) {
print('Document data: ${documentSnapshot.data()}');
} else {
print('Document does not exist on the database');
}
});
this code Always return to else
From the docs:
When you delete a document, Cloud Firestore does not automatically delete the documents within its subcollections. You can still access the subcollection documents by reference. For example, you can access the document at path /mycoll/mydoc/mysubcoll/mysubdoc even if you delete the ancestor document at /mycoll/mydoc.
Non-existent ancestor documents appear in the console, but they do not appear in query results and snapshots.
A document can exist even if one or more its ancestors don't exist. For example, the document at path /mycoll/mydoc/mysubcoll/mysubdoc can exist even if the ancestor document /mycoll/mydoc does not. The Cloud Firestore data viewer displays non-existent ancestor document as follows:
In a collection's list of documents, the document IDs of non-existent ancestor documents are italicized.
In a non-existent ancestor document's information panel, the data viewer points out that the document does not exist.
Since your document name is italicized, which means you either deleted the document or added the subcollection to an empty document which it seems you might have done according to your screenshot. Therefore to solve the issue delete the collection group and add the document with data:
FirebaseFirestore db = FirebaseFirestore.instance;
db.collection("group").doc("dialog").set({"name" : "peter"}).then((value){
db.collection("group").doc("dialog").collection("Tkxij").add({"test" :"test"});
});
Also queries are shallow, meaning if you are referencing a document then you will only get the data of that document, you won't get the data inside the subcollections.
I have added the code for your problem hope this clears your doubt, feel free to ask if you have any doubt.
getData( ) async{
final collectionData = await FirebaseFirestore.instance
.collection('groups').get();
//this forEach method will give every document of that collection
collectionData.docs.forEach((doc) {
final docData = doc.data();
final fieldData = docData['fieldName'];
});
}

Create documents, sub collections in Firestore via flutter on screen loads

I want to achieve is when flutter screen loads a document should create in firestore in following order.
Document > Sub Collection > Document > Data Fields
I manage to create documents and sub collections in above order, but the first Document appear in italic. That's because the child collection, documents creating before parent document created.
But I couldn't able to fix the issue. I've modified the code now it's not even creating the document. Before this It created in italic mode. Now it's not at all.
Here is the code.
getCurrentUser().then((user) {
DocumentReference todayReference = firestoreInstance.collection('attendance').document(todayDate);
firestoreInstance.collection('profiles').where('user_id', isEqualTo: user).snapshots().listen((onData) {
onData.documents.forEach((f) {
CollectionReference todaySubCollection = todayReference.collection(f.documentID);
DocumentReference attendanceReference = todaySubCollection.document(f["name"].toString().toLowerCase());
Map<String,dynamic> mapData = new Map<String,dynamic>();
mapData['attendance_status'] = true;
mapData['in'] = true;
mapData['out'] = true;
firestoreInstance.runTransaction((transaction) async {
await transaction.set(attendanceReference, mapData);
});
});
});
});
Here getCurrentUser() is returning the logged in user id.
Each profiles assigned to a user.
So, What I'm trying to do is, once user logged in a document should create under attendance collection named today's date.
Then looping through each profiles where user_id is matched with logged in user, the matching results will be store as sub collection under today's date with profiles name field.
Then under the name (document), a transaction needs to run to set details like attendance_status, in & out.
Following images will show how previously documents created.
I need to find a way to create documents, collection without in italic mode. Any help would be appreciated.
"Italicized" documents are virtual/non-existent as mentioned in the docs. If a document only has a sub-collection, it will be a virtual/non-existent document. A workaround for this is by writing fields in the document, like what you've mentioned in the comments.

How to monitor entire subcollection using transaction?

Follow this answer I am try to implement using transaction to monitor entire Firestore subcollection for new document added. Basically I only want write new document to subcollection if there is only one document. I need use transaction to avoid race condition resulting in >2 document in subcollection. Max should be 2.
How to use transaction to monitor document added to subcollection?
I am try long time to do but cannot solve.
I am experiment use iterate through subcollection for document but not know how to do this through transaction.
My code so far (maybe wrong method):
Firestore.instance.runTransaction((transaction) async {
final CollectionReference collectionRef = ref
.document(‘document’).collection(‘subCollection’);
List<DocumentSnapshot> subCollectionDocsSnapshot = [];
await collectionRef.getDocuments().then((querySnapshot) =>
querySnapshot.documents.forEach((document) {
subCollectionDocsSnapshot.add(document);
}
));
final DocumentReference newDocRef = collectionRef.document(docName);
await transaction.set(
newDocRef,
{‘docName’: docName,
}
);
});
How to solve?
Thanks!
UPDATE:
I have try add also transaction.get() to iterate through subcollection docs but it have no effect on race condition:
subCollectionDocsSnapshot.forEach((document) {
transaction.get(document.reference);
});
This isn't supported by Firestore transactions. Within a transaction, you can only find a document by its ID. You can't transact on the entire contents of a collection, and have that transaction retry if an new document is added while in the middle of the transaction. You also can't transact on the results of a query.
Instead, consider having a different document in another collection that counts the number of documents in a collection, and use that in your transaction. Or, at the very least, a document that records a boolean indicating whether or not the collection has >2 documents.

Resources