4
votes

What would be the good approach to design following swipe card style app with skip functionality?

Core functionality of the app I'm working on is as follows.

  • On the main page, a user first make a query for the list of the posts.
  • list should be sorted by date in reverse chronological order or some kind of internal score that determines the active post (with large number of votes or comments etc)
  • A each post is shown to user one by one in the form of a card like tinder or jelly style feed.
  • For each card, user can either skip or vote for it.
  • when user consumes all cards fetched and make query again for next items, skipped or already voted card by the current user should not appear again.

Here, the point is that a user could have huge number of skipped or voted post since user only can skip or vote for a post on the main page.(user can browse these already processed items on his/her profile)

The approaches I simply thought about are

1.to store the list of skipped or voted post ids for each user in somewhere and use them in the query with $nin operator.

db.posts.find({ _id: {$nin: [postid1,...,postid999]} }).sort({ date: -1 })

2.to embed all the userId of users that voted or skipped the post to an array and query using $ne operator

{ 
  _id: 'postid',
  skipOrVoteUser: ['user1', 'user2' ...... 'user999'],
  date: 1429286816366
}

db.posts.find({ skipOrVoteUser: {$ne: 'user1'} }).sort({ date: -1 })

3.Maintaining feedCache for each user and fanout on write.

FeedCache

{
  userId: 'user1',
  posts: [{id:1, data: {..}}, {id:2, data: {...}},.... {id:3, data: {...}}]
}

Operations: -When a user create a post, write copy of the post to all user's feed cache in the system. -Fetch posts from the user's feed cache. -When the user vote or skip a post, delete the post from his/her feed cache.

But since the list of the posts that user skipped or voted is ever growing and could be really large as time goes. I'm concern that this query would be too slow with large number of list for $nin for approach 1.

Also with approach 2, since all user on the system(or many depending on the filtering) could either vote or skip for a post, embedded user array of each post could be really large( max with number of all user) and performance of the query with $ne will be poor.

With approach 3, for every post created, there will be too much write operation and It won't be efficient.

What would be the good approach to design schema to support this kind of functionality? I've tried come up with good solution and could not think of better solutions. Please help me to solve this problem. Thanks!

1

1 Answers

0
votes

On a relational database I would use approach 1. It's and obvious choice as you have good SQL operators for the task and you can easily optimize the query.

With document databases I would choose approach 2. In this case there is a good chance the vote/skip list remaining relatively small as the system grows.