我使用下面的代码删除Firestore中集合中的所有文档。我的问题是,如何执行一个函数,它将使用已删除文档的数组返回'deleteCollection'的结果(promise)?我想循环遍历所有文档。我当然可以先查询所有数据,然后遍历它,然后再执行这个函数,但是数据会被读取两次。
另一种选择是创建一个空的全局变量,其中delete函数添加doc。但这有多安全?如果我要删除两个巨大的集合,则该阵列将填充两个不同的文档。这也不正确。
我也尝试修改'new Promise'返回,但是这个函数参数只能包含resolve或reject,没有数组。
所以我想要一个调用deleteCollection的函数,而不是想要遍历已删除的数据。当我只想读取一次数据时,这可能吗?
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;
}
}
答案 0 :(得分:1)
首先,请避开object(FilterCriteria):
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
语法,这样可以简化代码并使算法更易于理解:
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);
}
}
创建一个空的全局变量,其中delete函数添加doc。但这有多安全?如果我要删除两个巨大的集合,则该阵列将填充两个不同的文档。这也不正确。
不,不要这样做。只需通过递归调用将结果填充的数组作为参数传递,最后将其返回:
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;
}
}