Firestore 构建多对多

Firestore structuring many-to-many

在 Firebase 实时数据库中,我习惯于以这种方式组织关系:

/projects/{projectId}
/users/{userId}
/project-members/{userId}/{projectId}/true

根据 Firestore 文档 (https://firebase.google.com/docs/firestore/manage-data/structure-data#subcollections) 我应该这样组织:

/users/{userId}
/projects/{projectId}
/projects/{projectId}/members/{userId}/true (???)

但是我正在努力解决这个问题,有人可以给我提示吗?

第一次尝试:

return db.collection("projects").add({
  name: "Project Name",
  members: {
    [userId]: true
  }
});

可以存储,但我发现无法删除。 我相信,因为该项目是一个独特的文件。

// It doesn't work
return db.doc(`projects/${projectId}/members/${userId}`).delete()

第二次尝试:

因为 true 不是一个对象所以它不起作用:

db.collection("projects").doc(projectId).collection("members").doc(userId).set(true);

编辑:

根据Michael的回复,第一种情况要删除:

return db.doc(`projects/${projectId}`).update({
  [`members.${userid}`]: firebase.firestore.FieldValue.delete()
});

您的第一次尝试创建了一个存储在 /projects/[auto-id] 的文档,其内容为 {name: "Project Name", members: { "[user-id]": true } }

这不是子集。 /projects/[auto-id] 是一个包含所有成员资格的单个原子文档。所以要删除整个项目文件,你会这样做:

db.doc(`projects/${projectId}`).delete()

要在文档的 members 字段中添加/删除单个项目,您可以使用 update()set(){merge: true} 选项。但是要确定用户是否是项目的成员,您需要阅读整个文档。任何有权访问该文档的用户都可以看到所有成员,这可能是合意的,也可能不是合意的。此外,您可能 运行 陷入争用问题,因为单个文档只能每秒写入一次。

您的第二次尝试更接近实时数据库方法,而且可能更可取。它使用 members 子集合,每个成员都有一个单独的文档。但是正如您发现的那样,您不能只将 "true" 写为文档的内容。所以你需要写一些更实质性的东西,比如:

db.collection("projects").doc(projectId).collection("members").doc(userId).set({membership: true});

您可以使用 .remove() 删除此类文档。并使用 .get().

阅读