1
votes

In Firebase Realtime Database I was used to organize relations this way:

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

According to the Firestore docs (https://firebase.google.com/docs/firestore/manage-data/structure-data#subcollections) I should structure this way:

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

But i'm struggling with it, can someone give me a hint?

First try:

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

It works to store, but I found not possible to delete. I believe because the project is a unique document.

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

Second try:

Because true is not an object it doesn't work:

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

Edit:

According to Michael response, to delete in the first case:

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

1 Answers

2
votes

Your first try creates a document stored at /projects/[auto-id] with contents {name: "Project Name", members: { "[user-id]": true } }

This is not a subcollection. /projects/[auto-id] is a single atomic document that contains all membership within it. So to delete the entire project document, you would do:

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

To add / remove individual items in the members field of the document, you could use update() or set() with the {merge: true} option. But to find out whether a user is a member of the project, you'd need to read the entire document. And any user that has access to the document would be able to see all the members, which may or may not be desirable. Also, you could run into contention issues as a single document is only meant to be written around once per second.

Your second attempt is closer to the Realtime Database approach, and probably preferable. It makes use of a members subcollection with a separate document for each membership. But as you found out, you can't just write "true" as the contents of a document. So you'd need to write something more substantial like:

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

And you could delete such a document using .remove(). And read it using .get().