1

Building a react app with firebase firestore where users can friend each other and upvote each other’s posts. However, you can only see upvotes made by mutual friends.

Ie: if bob likes joe’s post.

If I am friends with joe and bob, I can see bob’s like.

If I am only friends with joe, I cannot see bob’s like.

How should I structure my data? I’m planning to create PostFeeds for each user:

— PostFeed (collection)
     — Uid (document)
         — Posts (collection)
              — Likes (collection)

If I write a new post, it gets added to all my friends’ post feeds. If I have 1000 friends, that post will be added to 1000 feeds.

I am storing the likes for every post inside each Post in PostFeed . So we can get likes without an extra query. So if bob likes joes post, the like will be added to every Post in joe’s friends’ Post feeds.

Ie: if joe likes bob’s post and bob has 500 friends. Bob’s post is on 500 friends’ PostFeeds. Joe’s like should be added to all 500 Posts in each PostFeed.

But likes are only visible if we are mutual friends.

Ie: if bob likes joe’s post, it will only be added to a users feed if we are mutual friends. So look through joe’s posts where bob is a mutual friend and add the like to those posts.

Is this scalable? Although most the write takes place in firebase functions, It seems very expensive write operation. Especially if a user Likes, the Unlikes, then Likes again. Or if I add a new friend, I need to add all upvotes that new friend made on mutual friends’ posts.

Is there a better way to handle this?

tzovourn
  • 1,293
  • 8
  • 18
Onichan
  • 4,476
  • 6
  • 31
  • 60
  • 1
    Just to understand, if you and I are mutual friends and someone who I am not friends with is the first to like your post, do I see your post as having no likes? – Thingamajig Sep 24 '19 at 04:44
  • 1
    You can take a look [this](https://stackoverflow.com/questions/46979375/firestore-how-to-structure-a-feed-and-follow-system/52153332), it might help you with an idea. – Alex Mamo Sep 24 '19 at 06:13
  • @DanFein yes, you would see the post has no likes because no mutual friends have liked the post. – Onichan Sep 24 '19 at 06:34
  • 1
    @AlexMamo thanks, thats the exact answer I've been using to understand this. But it doesn't explain if the same denormalization should be applied to `upvotes/likes`. Since they occur far more often than posts, this could get expensive quickly. Especially because `likes` are only visible to mutual friends, they should be stored in a collection within each user's feed like this `userFeed/userId/postId/likes` – Onichan Sep 24 '19 at 06:36
  • @AlexMamo Hoping to hear your thoughts on storing likes in firestore (especially in my case where likes are only visible if you are mutual friends). – Onichan Sep 25 '19 at 03:51

1 Answers1

0

I was sort of tempted to not write a decisive answer on this but after returning to the question, I'm leaning towards doesn't scale. Sure, you could argue Firebase can keep up with it and kudos to Firebase if it can, but the numbers just seem too high to ignore that it's likely not the best use of resources.

Let's take this example:

If I store every like for every post on every instance of that post, I could easily be at 500 writes just for a single like with no friend-checking. If I friend-check each of those, and each of the 500 exist because they are unique users, then that is 500 unique friend-checks.

If I have 500 followers and I like 20 things in one day, that's 10,000 times I'm checking to see if someone is my friend and 10,000 times I'm writing to a DB just for a like. I hope you anticipate more than 20 friends.

I think an alternative if you're building for scale in mind, is, can the data be stored in a way that enables calls that are done at runtime rather than storing all of this data?

Or maybe starting smaller in the beginning, can you store locally a list of all the users I'm friends with, and then pull a list of all the users who liked a post?

For what it's worth, if your example is true to the actual application of the code, I do think it's a very atypical situation and would result in a lot of users seeing 0 or few "likes" for each post. Sort of makes you question if the juice is worth the squeeze.

Thingamajig
  • 4,107
  • 7
  • 33
  • 61
  • Would this work: Store all friends locally with `uid` and `username`. The in firestore, when a user likes a post, add to `arrayLikes = [uid1, uid2, etc]` to all feeds that the post appears in (do not check if they are mutual friends, just save all likes). When displaying posts, compare the two arrays of locally stored friends with the `arrayLikes` in the post object. Would this be too resource intensive when displaying 15-30 posts? – Onichan Sep 24 '19 at 07:27
  • Or save my friendsListArray locally which contains `uids` of all my friends. When I like a post, I loop through `friendsListArray` and query the post author's friends list for mutual friends. Then update the post in their feed if they are mutual friends. – Onichan Sep 24 '19 at 08:17
  • That’s what I do for whether or not a user is subscribed to something specific in a long list of posts! I have a single document per specific categories of items. Each time I load the feed I get all items, look for the unique categories, and pull the specific doc for those categories. Then I just iterate through all of my items again and check the single category document. It seems to be working fine for now. At a time in the future I will need to pull in more than one document per category if they’re huge but it beats making a single call for every item! – Thingamajig Sep 24 '19 at 13:53