1

Wanted to see if there is a consensus on where the logic for showing liked/unliked buttons be kept, at the client view or on the database query. Pushing the logic to the query itself keeps it clean and consistent, but would require every query for the home page list of posts to be personalized and not allow caching of that request.

Setup: MongoDb database (or possibly neo4j), node.js api and application server, iOS mobile client and website. Most posts can have a dozen or so likes, but a few will have hundreds of likes. Most users will have liked 50 - 300 posts, with a few users liking thousands of posts.

My Use Case: User browses a list of recent popular posts, and sees a "like" or "unlike" button next to each post based on whether they've already liked the post.

Solution-

Approach 1: pass the userid in the query to the database and return a list of the most popular posts with an isLiked property calculated in the query.

Approach 2: Client app fetches and keeps in sync the liked ids for that user and the view determines whether to show the "like" or "unlike" button for any given list of posts. The lists of posts can be cached on the server or in a cdn and doesn't require any personalization.

Approach 3? Is there a more efficient way to do it at the rest api service layer?

MonkeyBonkey
  • 46,433
  • 78
  • 254
  • 460

1 Answers1

0

I guess you need to consider the benefits and drawbacks and see which one is the best.

MongoDB supports a monoatomic increment database command which can be very efficient. You won't even have to wait until the database layer confirms the insertion and simply display the number of 'likes' increased.

If, at around the same time, another user is reading the same article and you want to be 100% sure that he count is correct then, you'll probably don't want to do any caching.

Said that, you probably don't need to have that number to be a viewed consistent the millisecond after somebody has 'liked' a post. So you can cache the database information including the count and hit the database every x amount of minutes.

Take note that blog posts are very popular in the first couple of days and then not anymore.

Just out of curiosity you might find this interesting: a video the YouTube video count system, which the count stays at 301 for sometime for verification and multi-datacenter reasons. http://www.youtube.com/watch?v=oIkhgagvrjI

Gianfranco P.
  • 10,049
  • 6
  • 51
  • 68
  • The issue I'm having is the personalized "isLiked" property and not the count per se. Incrementing the count has been easy and well performing, but the biz logic of how to show whether this user has already liked this post in a scalable way is the issue.. – MonkeyBonkey Nov 13 '12 at 12:32
  • I think you should cache this perhaps in the browser localstore, as the user would more likely see the same article on the same device/browser. But you would still need to query the database or some mid-level cache if he tries to read the article from another device or browser without localcache. -- If you prefer to keep the architecture simple, probably 'scaling out' with MongoDB will scale your reads, once your news app becomes popular. This is done via [sharding](http://docs.mongodb.org/manual/core/sharding/) – Gianfranco P. Nov 14 '12 at 16:26
  • caching locally in approach 2 could work but it seems like it would become very complex and error prone with the syncing. Sharding wouldn't help in this case since it's not the size of the database that's the issue but the number of likes each post would get and it doesn't make sense to shard individual records. – MonkeyBonkey Nov 15 '12 at 13:29
  • Each like is going to be linked to a specific user. This has to be unique and indexed so, think you can work with collection `userlike` `{ userid: Object(), postid: Object() }`. And then create a unique index on `userid`, `db.userlike.ensureIndex({userid:1, postid:1}, {unique: 1})`. With NoSQL databases you might need to have duplicate data to have greater performance – Gianfranco P. Nov 15 '12 at 17:34