1

I'm building an app where users can post, delete and also rank (like, dislike) each others' posts. And on the profile page user can also view posts that he ever liked.

Currently I'm thinking to make the structure something like that (true - for like, false for dislike, empty for no rating):

{
"ranks": {
    "post1": {
      "user1": "true",
      "user2": "false",
      "user3": "false"
    },
    "post2": {
      "user1": "true",
      "user3": "true"
    },
    "post3": {
      "user1": "false",
      "user2": "true",
      "user3": "true"
    }
  }
}

All seems pretty good until I need to retrieve all posts that a user ever liked. E.g. for user1 would be [post1,post2]. For user2 - [post3].

Then I was thinking to restructure it the following way:

{
"ranks_by_user": {
    "user1": {
      "post1": "true",
      "post2": "true",
      "post3": "false"
    },
    "user2": {
      "post1": "false",
      "post3": "true"
    },
    "user3": {
      "post1": "false",
      "post2": "true",
      "post3": "true"
    }
  }
}

However, this is even more inconvenient: what if I delete a post, how would I also delete all the related ranks? Can't figure out a query to find all users in ranks_by_user list which has post-n child. How would one solve such structure issue?

1 Answers1

1

So you are correct in your structures. With firebase the general consensus is you will have duplicate data. As for your second question with how to delete, since everything is flattened and there are no foreign keys you will have to wire up the query yourself. Based on your model something like this might work:

...child('ranks_by_user').orderBy('post2').equalTo(true).once('value', function(){
    //delete record
});
...child('ranks_by_user').orderBy('post2').equalTo(false).once('value', function(){
    //delete record
});

Issue will be it will be slow because post2 won't be indexed. Instead user your first model and you'd be able to query that record to see who liked/disliked it and then go and delete the entries in the other models record. This would be my recommendation. Here's some code (done in angular1) that would do that for you:

var postId = 'post1';
...child('ranks').child(postId).once('value', function(snapshot){
    angular.forEach(snapshot.val(), function(value, userId){
        ...child('ranks').child(postId).child(userId).remove();
        ...child('ranks_by_user').child(userId).child(postId).remove();
    });
});
Mathew Berg
  • 28,625
  • 11
  • 69
  • 90