在Firestore中的集合中删除所有文档后,返回所有文档 [英] Return all docs when all docs are deleted in a collection in Firestore
问题描述
我正在使用下面的代码删除Firestore中集合中的所有文档.我的问题是,如何执行一个函数,该函数将返回"deleteCollection"的结果(承诺)以及带有已删除文档的数组?我想遍历所有文档.我当然可以先查询所有数据,然后遍历它,然后执行此功能,但随后数据将被读取两次.
I am using the code below to remove all docs in a collection in Firestore. My question is, how to execute a function which will return the result (promise) of 'deleteCollection' among with an array with the deleted docs? I want to loop over all the docs. I surely can query all the data first, loop through it and than execute this function, but than the data gets read twice.
另一个选择是创建一个空的全局变量,在该变量中删除函数将添加文档.但是,这有多安全?如果我要删除两个巨大的集合,该数组将填充两个不同的文档.那也不是正确的.
Another option would be creating a empty global variable in which the delete function adds the doc. But how safe is this? If I am deleting two huge collections, the array gets populated with two different docs. That wouldn't be correct as well.
我还尝试修改了新的Promise"返回值,但是该函数参数只能包含"resolve"或"reject",不能包含数组.
I also tried to modify the 'new Promise' return, but that function parameters can only contain resolve or reject, no arrays.
所以我想要一个调用deleteCollection的函数,然后想要遍历已删除的数据.如果我只想读取一次数据,这可能吗?
So I want a function which calls the deleteCollection and than I want to loop over the deleted data. Is this possible when I want to read the data only once?
function deleteCollection(db, collectionRef, batchSize) {
var query = collectionRef.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) => {
if (snapshot.size == 0) {
return 0;
}
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;
}
process.nextTick(function() {
deleteQueryBatch(db, query, batchSize, resolve, reject);
});
})
.catch(reject);
}
根据Bergi的答案进行编辑
const results = deleteCollection(db, db.collection("deleteme"), 1)
//Now I want to work with the results array,
//but the function is still deleting documents
function deleteCollection(db, collectionRef, batchSize) {
return deleteQueryBatch(db, collectionRef.limit(batchSize), batchSize, new Array());
}
async function deleteQueryBatch(db, query, batchSize, results) {
const snapshot = await query.get();
if (snapshot.size > 0) {
let batch = db.batch();
snapshot.docs.forEach(doc => {
results.push(doc); <-- the TypeError
batch.delete(doc.ref);
});
await batch.commit();
}
if (snapshot.size >= batchSize) {
return deleteQueryBatch(db, query, batchSize);
} else {
return results;
}
}
推荐答案
First of all, avoid the Promise
constructor antipattern:
function deleteCollection(db, collectionRef, batchSize) {
var query = collectionRef.limit(batchSize);
return deleteQueryBatch(db, query, batchSize);
}
function deleteQueryBatch(db, query, batchSize) {
return query.get().then(snapshot => {
if (snapshot.size == 0) return 0;
var batch = db.batch();
snapshot.docs.forEach(doc => { batch.delete(doc.ref); });
return batch.commit().then(() => snapshot.size);
}).then(function(numDeleted) {
if (numDeleted >= batchSize) {
// I don't think process.nextTick is really necessary
return deleteQueryBatch(db, query, batchSize);
}
});
}
(您可能还想使用 async
/ await
语法,这实际上可以简化代码并使算法更易于理解:
(You might also want to use async
/await
syntax which really simplifies the code and makes the algorithm better understandable:
async function deleteQueryBatch(db, query, batchSize) {
const snapshot = await query.get();
if (snapshot.size > 0) {
let batch = db.batch();
snapshot.docs.forEach(doc => { batch.delete(doc.ref); });
await batch.commit();
}
if (snapshot.size >= batchSize) {
// await new Promise(resolve => process.nextTick(resolve));
return deleteQueryBatch(db, query, batchSize);
}
}
创建一个空的全局变量,在该变量中删除函数将添加文档.但是,这有多安全?如果我要删除两个巨大的集合,该数组将填充两个不同的文档.那也不是正确的.
creating a empty global variable in which the delete function adds the doc. But how safe is this? If I am deleting two huge collections, the array gets populated with two different docs. That wouldn't be correct as well.
不,不要这样做.只需通过递归调用将您要填充结果的数组作为参数传递,然后最后将其返回:
No, don't do this. Just pass the array that you're populating with the results as an argument through the recursive calls and return it in the end:
function deleteCollection(db, collectionRef, batchSize) {
return deleteQueryBatch(db, collectionRef.limit(batchSize), batchSize, []);
}
async function deleteQueryBatch(db, query, batchSize, results) {
const snapshot = await query.get();
if (snapshot.size > 0) {
let batch = db.batch();
snapshot.docs.forEach(doc => {
results.push(doc);
batch.delete(doc.ref);
});
await batch.commit();
}
if (snapshot.size >= batchSize) {
return deleteQueryBatch(db, query, batchSize, results);
} else {
return results;
}
}
这篇关于在Firestore中的集合中删除所有文档后,返回所有文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!