1

I’m building a simple app in firebase 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?

1 Answers1

0

This is not a good approach.

For example, if two people become friends after they have written posts, then past posts will not appear in their feed. Also, if people unfriend each other, then all the postfeeds would need to be updated.

Instead, it should only store the actual information that took place, which is:

  • Vote ID (unique ID for this record)
  • Post ID (being voted upon)
  • User ID of person who liked the post

All of the "friend" stuff is then calculated on top of this record, either in real-time or occasionally recalculated and cached.

You might want to investigate usage of a graph database to store all of these relationships instead of a relational database.

See: TAO: The power of the graph | Facebook

John Rotenstein
  • 241,921
  • 22
  • 380
  • 470
  • I’m using firestore which is a nosql database. If two people become friends after they have written posts, then posts should be copied to each of their feeds. This is not a relational database so denormalization is preferred to make queries as simple as possible. Did I misunderstand your answer? – user1763837 Sep 23 '19 at 13:56
  • So, if somebody has hundreds of posts, and suddenly friends somebody else, you'll need a process that back-copies those posts to each of the feeds? If people have hundreds of friends, then data will be duplicated hundreds of times. While this might appear more efficient for retrieval purposes, it will blow-out the storage and would take significant resources "behind the scenes" to update such records whenever people friend/unfriend. You should create a testbed that simulates such user interactions to determine whether such an architecture is scalable. – John Rotenstein Sep 23 '19 at 17:59
  • Yes in firebase duplicating data 10000 times to every friends feed is the preferred way to handle it. It’s actually not as expensive as you might think. See https://stackoverflow.com/questions/46979375/firestore-how-to-structure-a-feed-and-follow-system/52106363 – user1763837 Sep 23 '19 at 18:41