cybermach
cybermach

Reputation: 125

Database Design for "Likes" in a social network (MongoDB)

I'm building a photo/video sharing social network using MongoDB. The social network has a feed, profiles and a follower model. I basically followed a similar approach to this article for my "social feed" design. Specifically, I used the fan-out on write with bucket approach when users posts stories.

My issue is when a user "likes" a story. I'm currently also using the fan-out on write approach that basically increments/decrements a story's "like count" for every user's feed. I think this might be a bad design since users "like" more frequently than they post. Users can quickly saturate the server by liking and unliking a popular post.

What design pattern do you guys recommend here? Should I use fan-out on read? Keep using Fan-out on write with Background workers? If the solution is "background workers", what approach do you recommend using for background workers? 'm using Node.js.

Any help is appreciated!

Thanks, Henri

Upvotes: 2

Views: 5068

Answers (1)

Morrisda
Morrisda

Reputation: 1420

I think the best approach is: 1. increasing-decreasing a counter in your database to keep track of the number of like 2. insert in a collection called 'like' each like as a single document, where you track the id of the users who likes the story and the id of the liked story.

Then if you just need the number of likes you can access the counter data and it's really fast, instead if you need to know where the likes where from you will query the collection called 'like' querying by story id and get all users' ids who liked the story.

The documents i am talking about in the like collection will be like so:

{_id: 'dfggsdjtsdgrhtd'
'story_id': 'ertyerdtyfret',
'user_id': 'sdrtyurertyuwert'}

You can store the counter in the story's document itself:

{
...
likes: 56
}

You can also keep track of last likes in your story's document (for example 1000. last because mongodb's documents have limited size to 16 mb and if your application scales so much you will meet problem in storing potential unlimited data in a single document). With this approach you can easily query the 'likes' collection and get last likes.

When someone unlikes a story you can simply remove the like document from 'like' collection, or, as better approach, (e.g: you are sending notification when someone's story is liked), just store in that document that was unliked, so that if it will be liked again by the same user you will have checked that the like was already inserted and you won't send another notification.

example: first time insert:

{_id: 'dfggsdjtsdgrhtd'
'story_id': 'ertyerdtyfret',
'user_id': 'sdrtyurertyuwert'
 active: true}

When unliked update to this

{_id: 'dfggsdjtsdgrhtd'
    'story_id': 'ertyerdtyfret',
    'user_id': 'sdrtyurertyuwert'
     active: false}

When each like is added check if there's an existing document with the same story id and the same user id. If there is, if active is false it means the user already liked and unliked the story so that if it will be liked again you won't send already-sent notification!

Upvotes: 7

Related Questions