This question already has answers here:
Delete a Document with all Subcollections and Nested Subcollections in Firestore
(13 answers)
Closed 2 years ago.
The Document I am trying to Delete
I want to delete a document which is further having collections inside it. I am running this code
db.collection("users").document(uid)
.delete()
.addOnCompleteListener {
if (it.isSuccessful) {
Log.i("logcat", "Success")
} else {
Log.i("logcat", "Fail")
}
}
The output in Logcat is Success still I see the document present on the console. However when i mention the complete reference(db.collection("users").document("uid).collection("amount")........), individual documents inside it gets deleted but I need to delete the document with all its collections inside. Am I trying it the wrong way or some limitation of Firebase?
Welcome to Stackoverflow!
In this case to delete subcollections you need to read this:
https://firebase.google.com/docs/firestore/solutions/delete-collections
Basically you will need to use a recursive delete like this:
await firebase_tools.firestore
.delete(path, {
project: process.env.GCLOUD_PROJECT,
recursive: true,
yes: true,
token: functions.config().fb.token
});
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have a collection called market and it had two documents that I can confirm in firebase.
I am now trying to get the number of documents in that collection like this:-
getAllItemsForSell()async {
final snapshot = await Firestore.instance.collection('market').getDocuments();
final documents = snapshot?.documents;
print(documents); // []
}
The above function prints out '[]', what am I doing wrong?
I looked everywhere on the internet but nothing seems to be helping.
please help? I am new to the Flutter Firebase world, thanks in advance.
To see the number of documents in that specific collection try to get the documentId from users collection and iterate through it by passing it to market collection like this
int sampleNum =0;
getAllItemsForSell()async {
QuerySnapshot users = await Firestore.instance.collection('market').getDocuments();
for(DocumentSnapshot docs in users.documents){
QuerySnapshot doc = await Firestore.instance.collection('market').document(docs.documentID).collection('marketPosts').getDocuments();
sampleNum = doc.documents.length;
//posts = doc.documents.map((doc) => Post.fromDocument(doc)).toList();
}
print(sampleNum.toString() +' **********');
}
The query is working as expected. Your "market" collection doesn't actually have any documents in it - it's completely empty. When you see a document ID in italics in the console, that's means there is no document, but there are subcollections nested under that document. The ID is there in the console so you can click through to them.
See also:
Parent document is being marked as "deleted" (italics) by default
Why are non auto-generated document Ids are in italics in Firestore console?
Firestore DB - documents shown in italics
why you don't use Future<void> or any type before the function. if it dosn't work read the doc for FlutterFire here is the link https://firebase.flutter.dev/docs/firestore/usage#document--query-snapshots
and i think just changing getDocuments() to get() it's maybe work,
Future<void> getAllItemsForSell()async {
final snapshot = await
Firestore.instance.collection('market').getDocuments();
final documents = snapshot?.documents;
print(documents); // []
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am trying to run multiple document updates within one firestore transaction and I am wondering whether or not this is an anti pattern.
I have a document named "Group" containing an array named "members" which contains different IDs from a users collection. Now I want to loop through all members and update the according user documents within one transaction. Is this possible?
I have tried to loop through all members with .forEach() but the problem is that .forEach() does not support async/await or the use of promises as far as I know.
The following should do the trick:
var firestore = firebase.firestore();
//.....
var groupDocRef = firestore.doc('collectionRef/docRef');
return firestore
.runTransaction(function(transaction) {
var arrayOfMemberIds;
return transaction
.get(groupDocRef)
.then(function(groupDoc) {
if (!groupDoc.exists) {
throw 'Group document does not exist!';
}
arrayOfMemberIds = groupDoc.data().members;
return transaction.update(groupDocRef, {
lastUpdate: firebase.firestore.FieldValue.serverTimestamp()
});
})
.then(function() {
arrayOfMemberIds.forEach(function(memberId) {
transaction = transaction.update(
firestore.collection('users').doc(memberId),
{ foo: 'bar' }
);
});
return transaction;
});
});
This will work because the update() method returns the Transaction instance which can be used for chaining method calls.
Note also that we must update the initial groupDoc. If not, the following error will be thrown: FirebaseError: "Every document read in a transaction must also be written.". In the example above we just update a lastUpdate field with a Timestamp. It's up to you to choose the update you want to do!
You can easily test the transactional aspect of this code by setting some security rules as follows:
service cloud.firestore {
match /databases/{database}/documents {
match /collectionRef/{doc} {
allow read: if true;
}
match /users/{user} {
allow read: if false;
}
}
}
Since it is not possible to write to the users collection, the Transaction will fail and the collectionRef/docRef document will NOT be updated.
Another (even better) way to test the transactional aspect is to delete one of the users document. Since the update() method fails if applied to a document that does not exist, the entire Transaction will fail.
I have an issue of knowing when to add or update an entry to a Firebase Firestore database.
Using doc_ref.set will add a document if it does not exist. It will also override all of a documents fields if it already exists and set is called.
Using doc_ref.update will update fields of a document if the document exists. If the document does not exist, nothing happens.
How do I add a new field to a document if the field does not currently exist, or update the field if it does exist? I could read the database and check if the field exists, and then use either set or update, but surely there is an easier way?
What you're looking for is the merge option in the set operation. From the documentation on setting a document:
var cityRef = db.collection('cities').doc('BJ');
var setWithMerge = cityRef.set({
capital: true
}, { merge: true });
If you're not sure whether the document exists, pass the option to merge the new data with any existing document to avoid overwriting entire documents.
I had similar problem, but I wanted to update array field using FieldValue.arrayUnion, FieldValue.arrayRemove. Therefore could not use set/merge.
To avoid checking if document exists before update (costs 1 read), I wrapped update statement with try/catch and check for error code 5 (NOT FOUND). In this case, set value instead of update.
Code example:
try {
await docRef.update({
arrayField: admin.firestore.FieldValue.arrayUnion(...dates),
});
} catch (error) {
if (error.code === 5) {
// Error: 5 NOT_FOUND: no entity to update:
await docRef.set({
arrayField: dates,
});
}
}
This question already has answers here:
Google Firestore - How to get several documents by multiple ids in one round-trip?
(17 answers)
Closed 3 years ago.
I have a list of DocumentID's that I want to use in a query and return data for only those documents.
The following code will return with 0 documents:
Future<QuerySnapshot> _getGroupsList(DocumentSnapshot data) async {
List<String> _localGroupIDs = List.from(data.data['MyGroups']);
CollectionReference colRef = Firestore.instance.collection('Groups').reference();
Query query = colRef.where('id', isEqualTo: _localGroupIDs);
QuerySnapshot querySnapshot = await query.getDocuments();
return querySnapshot;
}
However if I remove the query and just get run getDocuments() on the collection reference I can see that all the documents are available.
I have tried to do what was suggested here, Is FieldPath supported in Flutter? , but it didn't seem to work for me. I was constantly getting errors.
I was also digging around here https://github.com/flutter/plugins/blob/master/packages/cloud_firestore/android/src/main/java/io/flutter/plugins/firebase/cloudfirestore/CloudFirestorePlugin.java and I noticed that FieldPath.documentID() (on line 265) is being used but I can't see anyway to access it.
Does anyone know how to query against the DocumentID using Flutter and Firestore?
var test = await Firestore.instance.collection('Note').document(id).get();
try this pass the id of the document you need.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I have a flutter app that basically acts as a filter app for another app, meaning i can scroll through certain posts and decide whether to delete them from this app so they dont show up on the other main app.
My question is, since Firestore does not support deleting subcollections, what happens if i just delete the document of the post and ignore the remaining subcollections of things like comments? Is it possible that firestore will later assign a random postId with the same as the one previously deleted and end up showing a deleted post's comments and subcollection info? Because it says on firestore that the ancestor document that doesnt exist for a subcollection that does will not show up in queries does that mean that no other post will be created with the same postId?
Basically Is there any harm for not deleting the subcollections, if there is what do you recommend i do about it, manually delete it?
You can use firebase functions to delete collections when a document is deleted. In other words, you would code a function that executes every time a document (in your case post) is deleted. Then you would go through your subcollections and delete them in the function.
To delete a collection I use this code (I didn't code this):
/**
* Delete a collection, in batches of batchSize. Note that this does
* not recursively delete subcollections of documents in the collection
*/
function deleteCollection (db, collectionRef, batchSize) {
var query = collectionRef.orderBy('__name__').limit(batchSize)
return new Promise(function (resolve, reject) {
deleteQueryBatch(db, query, batchSize, resolve, reject)
})
}
function deleteQueryBatch (db, query, batchSize, resolve, reject) {
query.get()
.then((snapshot) => {
// When there are no documents left, we are done
if (snapshot.size === 0) {
return 0
}
// Delete documents in a batch
var batch = db.batch()
snapshot.docs.forEach(function (doc) {
batch.delete(doc.ref)
})
return batch.commit().then(function () {
return snapshot.size
})
}).then(function (numDeleted) {
if (numDeleted <= batchSize) {
resolve()
return
}
else {
// Recurse on the next process tick, to avoid
// exploding the stack.
return process.nextTick(function () {
deleteQueryBatch(db, query, batchSize, resolve, reject)
})
}
})
.catch(reject)
}
Is it possible that firestore will later assign a random postId with the same as the one previously deleted
The collisions of ids in this case is incredibly unlikely and you can/should assume they'll be completely unique. So you don't have to be concerned about it because that's why those ids were designed for, to be unique.
This built-in generator for unique ids that is used in Firestore when you call CollectionReference's add() methods or CollectionReference's document() method without passing any parameters, generates random and highly unpredictable ids, which prevents hitting certain hotspots in the backend infrastructure.
does that mean that no other post will be created with the same postId?
Yes, not other document will be created with the same id.
Basically Is there any harm for not deleting the subcollections
There is not. You can do it in two ways, client side my getting all documents within that subcollection and deleting them in smaller chunks or using a function as #jonasxd360 mentioned in his answer.