What is the better way to implement shared record with ability to remove it by each user

38 views
Skip to first unread message

Igor Khomenko

unread,
Apr 26, 2016, 8:51:12 AM4/26/16
to mongodb-user
I have a MongoDB record, for example, called **Letter**. 

This letter can be sent to some group of users, so many users have an access to it.

A **Letter** can be sent in a context of **Topic** that is shared between group of users.

So, the **Topic** model has the following structure:

 - _id
 - name (String)
 - users_ids (Array of users ids, that can send letters withing this topic)

Also, each user can remove a letter for himself. 

I have some concerns regarding how to implement/store this model with MongoDB.

**Variant 1:**

MongoDB record, fields:

 - _id (ObjectId)
 - topic_id (ObjectId)
 - text (String)
 - deleted_for_users_ids (Array)

When a user deletes a record then we add his ID to the **deleted_for_users_ids** array. 

To retrieve records I use the following request:

    db.letters.find({topic_id: 'X', deleted_for_users_ids: {$nin: 'user_id'}})

It's not good because we can't add an Index for 'nin' filter in MongoDB. 

**Variant 2:**

MongoDB record, fields:

 - _id (ObjectId)
 - text (String)
 - topic_id (ObjectId)
 - accesible_for_users_ids (Array) 

When a user creates a record then the **accesible_for_users_ids** array will be equal to the **topic.user_ids** array.

When a user deletes a record then we remove his ID to the **deleted_for_users_ids** array. 

To retrieve records I use the following request:

    db.letters.find({topic_id: 'X', accesible_for_users_ids: {$in: 'user_id'}})

It's better, now we can use Index because a filter 'in' can be covered by index.

But I see that indexes for array use a lot of RAM, which is not good.

====

So 2 concerns: RAM and speed.

Do you have any other ideas how to implement logic like that on MongoDB

Kevin Adistambha

unread,
May 10, 2016, 1:30:48 AM5/10/16
to mongodb-user

Hi Igor,

A Letter can be sent in a context of Topic that is shared between group of users.

So, the Topic model has the following structure:

  • _id
    • name (String)
    • users_ids (Array of users ids, that can send letters withing this topic)

Also, each user can remove a letter for himself.

Both of your concerns for the two variants you posted was correct. The $nin query in variant 1 cannot use an index, hence performance will likely suffer. Additionally in variant 2:

  • _id (ObjectId)
    • text (String)
    • topic_id (ObjectId)
    • accesible_for_users_ids (Array)

If a letter is accessible to all users by default, you would have to insert the whole user array into the accesible_for_users_ids field every time a new letter is inserted. If your user array is large, these inserts will be expensive. This may not be ideal for performance reasons.

If applicable to your use case, you may find the Socialite project useful as a guide. Socialite explores the design, scaling, and challenges of creating a social network status feed in a series of presentations in MongoDB World 2014. The presentation series consists of:

  1. Design overview and scaling
  2. Managing the social graph
  3. Scaling the data feed

Best regards,
Kevin

Reply all
Reply to author
Forward
0 new messages