在Firestore中的集合中删除所有文档后,返回所有文档 [英] Return all docs when all docs are deleted in a collection in Firestore

查看:40
本文介绍了在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆