当前位置: 首页 > 知识库问答 >
问题:

删除不存在的祖先文档和子集合

许曦
2023-03-14

我想清理我的收集数据。我有集合名称“团队”。它具有数据和子集合名称“玩家”。

我通过Firestore的简单删除查询删除了“团队”文档,但我们知道我们无法通过删除主/祖先docID来删除子集合(玩家)。我们必须从“玩家”集合中获取所有文档,然后首先删除它们。之后,我们应该删除祖先(团队的文档)文档,以便清除集合的所有内容。

不可能从“团队”集合中获取这些孤立文档。那么,如何从集合中清除这些文档呢?

~PS:我创建了一个Firebase云函数,可以在删除祖先文档的同时删除子集合文档。

exports.deleteOrphanedTeamsDoc = functions.firestore
  .document('teams/{teamID}')
  .onDelete(async (snap, context) => {
    var teamID = context.params.teamID;
    console.log("Deleted teamID --->>> " + teamID);

    const store = admin.firestore();
    var teamsPlayer = await store.collection('teams').doc(teamID).collection('players').get()

    teamsPlayer.docs.forEach(async(val) => {
      await store.collection('teams').doc(teamID).collection('players').doc(val.id).delete();
    });
  });

因此,在上述代码的帮助下,我也可以删除带有子集合的新团队docID。

但是我的“团队”收藏中所有可用的孤儿文档呢?

更新 1:

我尝试了雷诺·塔内克的代码,抱歉,但我是新来的,所以没有太多的想法。我点击了运行按钮,但遇到了一些问题

6:46:13.625 pm
scheduledFunction
Function execution took 12608 ms, finished with status: 'error'
6:46:13.622 pm
scheduledFunction
at processTicksAndRejections (internal/process/task_queues.js:97:5)
6:46:13.622 pm
scheduledFunction
at runMicrotasks (<anonymous>)
6:46:13.622 pm
scheduledFunction
at /workspace/index.js:161:53
6:46:13.622 pm
scheduledFunction
ReferenceError: promises is not defined 
6:46:01.018 pm
scheduledFunction
Function execution started

我认为问题就在这里。ReferenceError:promises没有定义。at

const parentsSnapshotsArray = await Promise.all(promises);

共有2个答案

罗乐意
2023-03-14

Firebase控制台通过这些斜体文档表明,这些文档实际上并不存在。这些文档不存在,要么是因为您没有创建它们,要么是您明确删除了它们。所以这些文档仍然会显示,因为它们下面有一个子集合。所以基本上文档的ID是以某种方式保留的,如果你将来需要做一些操作的话。

需要记住的一点是,在云Firestore中,文档和子集合的工作方式不同于文件系统文件和目录。总之,你不能删除不存在的东西。换句话说,因为在那个位置没有物理文档,所以您不能执行删除操作。

麹鸿煊
2023-03-14

但是我的“团队”收藏中所有可用的孤儿文档呢?

如您所述,您的Cloud Function不会为已删除的team文档触发。

要删除孤立的播放器文档,您可以做的是每X分钟/小时运行一次预定的云功能。

以下云函数使用集合组查询来获取所有播放器文档并删除它们。请注意,您需要有一个 Firestore 索引才能进行查询。还要注意我们如何使用 Promise.all() 以便在所有异步工作完成后返回唯一的 Promise;这是正确管理云函数生命周期的关键。

exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) => {

    const playersRef = admin.firestore().collectionGroup('players');
    const playersSnap = await playersRef.get();

    const promises = [];
    playersSnap.forEach((doc) => {
        promises.push(doc.ref.delete());
    });
    return Promise.all(promises)

});

现在,我们需要添加一个额外的业务逻辑。仅当父团队文档不存在时,才应删除玩家文档。

下面的代码应该可以解决问题(未经测试):

exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun(async (context) => {

    const playersRef = admin.firestore().collectionGroup('players');
    const playersSnap = await playersRef.get();

    const docParentIdsToDelete = [];

    const docParentIdsTreated = [];
    const promisesParentDocs = [];
    playersSnap.forEach((doc) => {
        const parentTeamRef = doc.ref.parent.parent;
        const parentTeamId = parentTeamRef.id;
        if (docParentIdsTreated.indexOf(parentTeamId) < 0) {
            // We need to check if the parent exists
            promisesParentDocs.push(parentTeamRef.get());
            docParentIdsTreated.push(parentTeamId);
        }
    });

    const parentsSnapshotsArray = await Promise.all(promisesParentDocs);

    parentsSnapshotsArray.forEach(snap => {
        if (!snap.exists) {
            // The parent team doc DOES NOT exist. It is shown in italic in the Firebase console.
            // => We need to delete the players child docs
            docParentIdsToDelete.push(snap.id);
        }
    });
    
    const promisesDeletion = [];
    playersSnap.forEach((doc) => {
        const parentTeamId = doc.ref.parent.parent.id;
        if (docParentIdsToDelete.indexOf(parentTeamId) > -1) {
            // We need to delete the player doc
            promisesDeletion.push(doc.ref.delete());
        }
    });
    
    return Promise.all(promisesDeletion);
    
});

基本上,我们首先获取所有player文档。然后我们循环检查父teamdoc是否存在(使用数组来最小化查询次数)。如果它不存在,我们将其ID推送到数组=

 类似资料:
  • 据我所知,我可以使用云函数以某种方式实现这一点?我试着阅读云函数,但我很迷路。是否有一种方法可以触发云函数,在用户更新帖子时删除子集合中的所有文档?

  • 当使用Firebase控制台时,可以看到所有文档和集合,甚至是路径中包含不存在的“文档”的子集合。 有没有可能,以某种方式,列出这些文件。既然控制台能做到,看来肯定有办法。如果有可能找到这些文档,是否可以创建一个查询来获取所有不存在但仅限于具有嵌套子集合的文档?(因为所有不存在的文档集将是无限的)

  • 问题内容: 我正在寻找清除整个收藏夹的方法。我看到有一个批处理更新选项,但这需要我知道集合中的所有文档ID。 我正在寻找一种简单地删除集合中每个文档的方法。 谢谢! 编辑:下面的答案是正确的,我使用以下方法: 问题答案: 没有API可以一次性删除整个集合(或其内容)。 从Firestore文档中: 要在Cloud Firestore中删除整个集合或子集合,请检索集合或子集合中的所有文档并将其删除。

  • 通过指定文档的 /index/type/id 路径可以删除文档: $params = [ 'index' => 'my_index', 'type' => 'my_type', 'id' => 'my_id' ]; // Delete doc at /my_index/my_type/my_id $response = $client->delete($params);

  • 所以我有2个系列, 用户(收藏) 检查(收集) 用户只有名为不同电子邮件地址的文档 检查将文档命名为不同的电子邮件地址,然后每个文档都有另一个名为“assignedToMe”的集合,然后此集合具有命名为某些唯一 ID 的不同文档。 我想做的是,每当我删除一个用户,我希望它的文件命名为他的电子邮件地址被删除,以及从检查(收集)。 我在这里遇到的问题是,我能够从用户(集合)中删除该用户,但无法删除该特

  • 我如何删除一个特定的文档中的一个集合在fiRecovery使用反应? 我在这里和谷歌上看了看,但我没有发现任何内在相关的东西。 我只是设法从我的集合中删除索引[0]的文档。 这状态idDoc接收所有id文档。 如果我只是传递. doc(idDoc),我会得到以下错误: Firebase Error: Function Collection Reference.doc()要求它的第一个参数是非空字符