1

I have an application where a user can create lists.

The user can share a list with other users. I already manage to create the sharing part, the one I'm having issues is with the delete part. I want that when a user deletes a list that is shared , this list is also deleted from the other users.

This delete will be made only by list owner.

So a scenario will be:

  • User A creates a List with pushID = 1.
  • This list is added in the following firebase ref: /userList/$userAID/$pushID.
  • User A shares list with User B and User C.
  • This list is added in the following firebase ref: /userList/$userBID/$pushID and /userList/$userCID/$pushID.
  • User A deletes list with pushID = 1.

So in my

So i have this schema:

userList: {
   2xYnKcZFEdPYWfUJ3E63yQEDShe2: {
     -Kt7lXiY0Yt-oDcV38L5
   }
   KtQHkXMSwKSByZ1rmTRwjDmSYnE3: {
     -Kt7lXiY0Yt-oDcV38L5: {}
     -Kt9XP91hjwcwgcBSgbc: {}
   }
   XHpMVoRqcCdzwTP70L29Lza1ibD3: {
     -Kt7lXiY0Yt-oDcV38L5: {}
   }
}

In high level this will be:

userList: {
       userID: (A) {
         -listID : (1) {}
       }
       userID: (B) {
         -listID: (1) {}
         -listID: (2) {}
       }
       userID: (C) {
         -listID: (1) {}
         -listID: (3) {}
         -listID: (4) {}
       }
    }

The current code I have to do this is the following:

const ref = firebase.database().ref('userList');
    ref.once('value')
      .then((snapshot) => {
        snapshot.forEach((childSnapshot) => {
          ref.child(childSnapshot.key)
            .once('value')
            .then((snapshot2) => {
              snapshot2.forEach((childSnapshot2) => {
                if (childSnapshot2.key === uid) {
                  ref.child(childSnapshot2.key)
                    .remove();
                }
              });
            })
            .catch(() => {
              console.log('error2');
            });
        });
      })
      .catch((error) => {
        console.log(error);
      });

What I'm doing in this code is, first fetching ALL the list inside userList, by getting the key I manage to jump to the userID child. Inside this node once again I manage to jump inside the pushID where I make a validation of checking if current key is equal to the UID of the list i want to delete, if so I do a remove().

I feel there must be a better way of telling Firebase to go directly to pushID and find all of those that are equal to the UID of the list I want to delete and then do it.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
atsepa
  • 45
  • 6
  • Im looking for something like: firebase.database().ref('userList').child().child(uid).remove(); I know child() can't be empty. But something like that – atsepa Sep 11 '17 at 02:20

1 Answers1

4

There is no way to do a server-side delete of multiple items based on a condition with the Firebase Database. You must first retrieve the items (or just their IDs) matching the condition and then delete those.

However, you can delete the list itself and all references to it in one go by using a multi-path update.

I'd also recommend keeping a list of all the UIDs you've shared a specific list with, so that you don't have to loop over all users. Keeping many-to-many relations in both directions is quite common in Firebase and other NoSQL databases.

For more see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Yeah, at the end I figure the best way will be keeping a record of all users the list is been shared and with that loop to delete. But what would you think is best practice ... using the milti-path update or having a list of all users you are sharing with and then loop? – atsepa Sep 11 '17 at 04:45
  • The two typically go hand-in-hand: you read the list of locations/keys from the database, loop over that to build a collection of paths to update and then fire a single multi-location update. – Frank van Puffelen Sep 11 '17 at 14:41