Как удалить несколько документов из Cloud Firestore?
Какой лучший способ удалить многие (не все) документы из Cloud Firestore?
Официальная документация содержит информацию об удалении одного документа и всех документов: https://firebase.google.com/docs/firestore/manage-data/delete-data.
7 ответов
Чтобы удалить несколько документов, вы можете сделать одну пакетную запись. WriteBatch
класс имеет delete()
метод для этой цели.
Я ожидаю, что производительность будет очень похожа между BatchedWrite
и несколько DocumentReference.delete
хотя звонит. Как в: Я ожидаю, что оба они будут достаточно эффективными для случая, когда пользователь выбирает документы, которые будут удалены. Если вы обнаружите, что это не так, поделитесь кодом, который воспроизводит проблему производительности.
Поскольку это первый результат при поиске « как удалить несколько документов в Firestore », я хотел поделиться рабочим фрагментом кода, который не только делает то, что запрашивает OP, но и разбивает ваши пакеты на куски, чтобы избежать достижения предела 500 коммитов на пакет .
const deleteEmptyMessages = async () => {
const snapshot = await firestore.collection('messages').where('text', '==', '').get();
const MAX_WRITES_PER_BATCH = 500; /** https://cloud.google.com/firestore/quotas#writes_and_transactions */
/**
* `chunk` function splits the array into chunks up to the provided length.
* You can get it from either:
* - [Underscore.js](https://underscorejs.org/#chunk)
* - [lodash](https://lodash.com/docs/4.17.15#chunk)
* - Or one of [these answers](https://stackoverflow.com/questions/8495687/split-array-into-chunks#comment84212474_8495740)
*/
const batches = chunk(snapshot.docs, MAX_WRITES_PER_BATCH);
const commitBatchPromises = [];
batches.forEach(batch => {
const writeBatch = firestore.batch();
batch.forEach(doc => writeBatch.delete(doc.ref));
commitBatchPromises.push(writeBatch.commit());
});
await Promise.all(commitBatchPromises);
};
FirebaseFirestore db = FirebaseFirestore.getInstance();
WriteBatch writeBatch = db.batch();
for (int i=0;i<cartList.size();i++){
DocumentReference documentReference = db.collection("Users").document(cartList.get(i).getProductId());
writeBatch.delete(documentReference);
}
writeBatch.commit().addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Do anything here
}
});
Надеюсь, это поможет
Я использовал для этого пакетную запись. Например, я удалил все документы, в которых поле «текст» пусто:
const emptyMessages = await firestore.collection('messages').where("text", "==", "").get()
const batch = firestore.batch();
emptyMessages.forEach(doc => {
batch.delete(doc.ref);
});
await batch.commit();
Надеюсь, это кому-то поможет
В вопросе не указан конкретный вариант использования. Но...
Одним из распространенных сценариев, когда пользователь может захотеть удалить несколько документов, может быть, например: удаление всех элементов из корзины покупок пользователя. (Но не из корзин других пользователей.)
Чтобы сделать это эффективно, вы должны использовать пакетную запись.Это позволяет выполнять несколько операций удаления одновременно.
Например, чтобы удалить сразу три документа:
WriteBatch batch = db.batch();
batch.delete(db.collection("cartItems").document("item1"));
batch.delete(db.collection("cartItems").document("item2"));
batch.delete(db.collection("cartItems").document("item3"));
batch.commit()
.addOnSuccessListener((result) -> {
Log.i(LOG_TAG, "Selected items have been deleted.");
})
.addOnFailureListener((error) -> {
Log.e(LOG_TAG, "Failed to delete selected items.", error);
});
Итак, если вы заранее знаете идентификаторы документов, это довольно просто:
public void removeSelectedItemsFromShoppingCart(List<String> itemIds) {
WriteBatch batch = db.batch();
CollectionReference collection = db.collection("cartItems");
for (String itemId : itemIds) {
batch.delete(collection.document(itemId));
}
batch.commit()
.addOnSuccessListener((result) -> {
Log.i(LOG_TAG, "Selected items have been removed.");
})
.addOnFailureListener((error) -> {
Log.e(LOG_TAG, "Failed to remove selected items.", error);
});
}
Но если вы не знаете идентификаторы документов заранее, вам, возможно, придется сначала запросить базу данных:
public void removeAllItemsFromShoppingCart(String userId) {
db.collection("cartItems")
.whereEqualTo("userId", userId)
.get()
.addOnSuccessListener((querySnapshot) -> {
WriteBatch batch = db.batch();
for (DocumentSnapshot doc : querySnapshot) {
batch.delete(doc.getReference());
}
batch.commit()
.addOnSuccessListener((result) -> {
Log.i(LOG_TAG, "All items have been removed.");
})
.addOnFailureListener((error) -> {
Log.e(LOG_TAG, "Failed to remove all items.", error);
});
})
.addOnFailureListener((error) -> {
Log.e(LOG_TAG, "Failed to get your cart items.", error);
});
}
Обратите внимание, что в приведенном выше коде используется одноразовое чтение, а не чтение в реальном времени. Что здесь критично, поэтому он не продолжает удалять документы после завершения операции.
btnDeleteSomeTasks.setOnClickListener{
for (ids in 0 until mRecyclerView.size){
val currentID = entryAdapter.snapshots.getSnapshot(ids).id
val reference = firestore.collection("allTasks")
.document(user.uid)
.collection("userTasks")
.document(currentID)
reference.delete()
notifyItemRemoved(ids)
}
}
В обновлении Firebase от марта 2023 года представлен метод удаления всех объектов, соответствующих нескольким условиям:
const q = query(collection(db, 'collectionid'),
and(where('fieldname', '==', surveyObject.uid),
where('array-of-objecst', 'array-contains', object)
)
);
const batch = writeBatch(db);
const objectsToDelete = await getDocs(q);
questionsToDelete.forEach(doc => {
batch.delete(doc.ref);
});
await batch.commit();