How can I implement an ordered array with mongodb without race conditions?

I'm new to mongodb, maybe this is a trivial question. I have two mongodb collections: userand post. The user can create and monitor several messages, and the entries are sorted by the date of the last change. There can be a very large number of users following a certain post, so I do not want to keep a list of subscribers in each mail document. On the other hand, one user probably will not follow more than a few thousand messages, so I decided to keep a list of object objects of subsequent messages in each user document.

In order to be able to quickly list the 50 most recently modified posts for this user, I decided to save the field last_updated_atalong with the post objectid.

The document is postquite simple:

{
    "_id" : ObjectId("5163deebe4d809d55d27e847"),
    "title" : "All about music"
    "comments": [...]
    ...
}

The document is useras follows:

{
  "_id": ObjectId("5163deebe4d809d55d27e846"),
  "posts": [{
    "post": ObjectId("5163deebe4d809d55d27e847"),
    "last_updated_at": ISODate("2013-04-09T11:27:07.184Z")
  }, {
    "post": ObjectId("5163deebe4d809d55d27e847"),
    "last_updated_at": ISODate("2013-04-09T11:27:07.187Z")
  }]
  ...
}

When a user creates or follows the message, I can just $pushsend ObjectIdand last_updated_atat the end of the list postsin the user's document. When a message changes (for example, when a comment is added to the message), I update the field last_updated_atfor this entry in all documents of the subscriber user. It’s pretty hard, but I don’t know how to avoid it.

50 , , , , last_updated_at , 50 .

, , : $push , $pull - , . , , . mongodb?

+5
1

, , , .

:

  • : (userID, postID, lastUpdated)
  • , update() multi:true upsert:true $set last_updated_at .
  • 50 , find() .
  • "" TTL ,

MongoDB 2.4

, MongoDB 2.4 , :

  • , .

, , 50 , :

db.user.update(
    // Criteria
    { _id: ObjectId("5163deebe4d809d55d27e846") },

    // Update
    { $push: {
        posts: {
            // Push one or more updates onto the posts array
            $each: [
                {
                    "post": ObjectId("5163deebe4d809d55d27e847"),
                    "last_updated_at": ISODate()
                }
            ],

            // Slice to max of 50 items
            $slice:-50,

            // Sorted by last_updated_at desc
            $sort: {'last_updated_at': -1}
        }
    }}
)

$push , $slice 50 . , $pull , :

db.user.update(
    // Criteria
    { _id: ObjectId("5163deebe4d809d55d27e846") },

    // Update
    { 
        $pull: {
            posts: { post: ObjectId("5163deebe4d809d55d27e847") }
        }
    }
)

, , , , , .

+9

All Articles