Javascript 在Firestore中删除集合中的所有文档时返回所有文档

Javascript 在Firestore中删除集合中的所有文档时返回所有文档,javascript,node.js,firebase,promise,google-cloud-firestore,Javascript,Node.js,Firebase,Promise,Google Cloud Firestore,我正在使用下面的代码删除Firestore集合中的所有文档。我的问题是,如何执行一个函数,它将返回一个包含已删除文档的数组中的“deleteCollection”的结果(承诺)?我想把所有的文件都循环一遍。我当然可以先查询所有数据,循环遍历它,然后执行这个函数,但是数据会被读取两次 另一个选项是创建一个空的全局变量,delete函数在其中添加文档。但这有多安全?如果我删除两个巨大的集合,数组将填充两个不同的文档。这也不正确 我还试图修改“newpromise”返回,但函数参数只能包含resolv

我正在使用下面的代码删除Firestore集合中的所有文档。我的问题是,如何执行一个函数,它将返回一个包含已删除文档的数组中的“deleteCollection”的结果(承诺)?我想把所有的文件都循环一遍。我当然可以先查询所有数据,循环遍历它,然后执行这个函数,但是数据会被读取两次

另一个选项是创建一个空的全局变量,delete函数在其中添加文档。但这有多安全?如果我删除两个巨大的集合,数组将填充两个不同的文档。这也不正确

我还试图修改“newpromise”返回,但函数参数只能包含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);
}
函数deleteCollection(db、collectionRef、batchSize){
var query=collectionRef.limit(batchSize);
返回新承诺(功能(解决、拒绝){
deleteQueryBatch(数据库、查询、批大小、解析、拒绝);
});
}
函数deleteQueryBatch(数据库、查询、批大小、解析、拒绝){
query.get()
。然后((快照)=>{
如果(snapshot.size==0){
返回0;
}
var batch=db.batch();
snapshot.docs.forEach(函数(doc){
批处理删除(文件编号ref);
});
返回batch.commit().then(函数()){
返回快照大小;
});
}).then(函数(numDeleted){
如果(numDeleted首先,避免:

(您可能还希望使用
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函数添加文档。但这有多安全?如果我删除两个大型集合,数组将填充两个不同的文档。这也不正确

不,不要这样做。只需将正在填充结果的数组作为参数通过递归调用传递,最后返回:

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;
  }
}

避免使用!@Bergi我从Google文档中复制了代码:哎哟。他们肯定也应该避免使用它。文档中的一个文件bug在哪里呢?@Bergi我用这个链接联系了他们几次:他们通常反应很快(~1天)。但我没有Firebase帐户,该联系人页面需要有人登录。感谢您的回答。但是,我收到以下错误“未经处理的承诺拒绝(拒绝id:1):TypeError:无法读取未定义的属性“push”。我尝试登录该帐户并将[]更改为new Array(),但没有帮助。我尝试了结果。push(“测试”),我仍然得到那个错误。此外,deleteCollection返回一个void,因此我不确定如果TypeError消失了,我如何才能得到结果。我尝试在deleteQueryBatch之前添加'return',但这并不等待deleteQueryBatch的返回。@J.Doe啊,我忘记了一堆
return
关键字并传递
结果
into递归呼叫。感谢您抽出时间创建此精彩答案。我联系了支持热线。我希望他们会对我在电子邮件中添加的您的答案发表评论。谢谢!
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);
  }
}
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;
  }
}