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

时间:2017-10-17 21:01:50

标签: javascript node.js firebase promise google-cloud-firestore

我使用下面的代码删除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;
  }
}

1 个答案:

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