Pash Shocky
Pash Shocky

Reputation: 66

mongodb array re-order and update

I am using mongo for storing private messages, and for example i have an array like so:

{
  "_id": { "$oid" : "520b842005ab0d0000000003" },
  "pmhistory": [
    {
      "sendername": "Tati",
      "preview": "Hey Man!",
    },
    {
      "sendername": "Dan",
      "preview": "Hey Moon!",
    },
    {
      "sendername": "Hellen",
      "preview": "Hello, Im proper!",
    },
  ],
  "user": { "$oid" : "520b842005ab0d0000000002" },
  "userid": "1"
}

If Dan sends a new message, I need to move his array entry to position 0 (pmhistory[0]) and update the preview field.

Now i am forced to issue two queries to the database, one with the $pull parameter, that takes out Dans entry from the pmhistory array and another with the $set parameter that adds Dans entry to the beginning of the pmhistory array.

Is it possible to use 1 query instead of two? Without getting have conflicting mods in update, because i am changing the size of the array.

Upvotes: 0

Views: 1369

Answers (2)

Derick
Derick

Reputation: 36774

I think the easiest would be to not rely on the array order in the first place. What I would do is add an additional field "last_update" to each subdocument, like:

{
  "_id": { "$oid" : "520b842005ab0d0000000003" },
  "pmhistory": [
    {
      "sendername": "Tati",
      "preview": "Hey Man!",
      "last_updated": 1376581408222,
    },
    {
      "sendername": "Dan",
      "preview": "Hey Moon!",
      "last_updated": 1376581406444,
    },
    {
      "sendername": "Hellen",
      "preview": "Hello, Im proper!",
      "last_updated": 1376581508111,
    },
  ],
  "user": { "$oid" : "520b842005ab0d0000000002" },
  "userid": "1"
}

Then, when Dan has a new message, you can just run a findAndModify like this:

db.so.findAndModify( { 
    query: { "pmhistory.sendername" : "Dan" }, 
    update: { 
        $set: { "pmhistory.$.last_updated" : (new Date).getTime() } 
    }, 
    new: true 
} );

Which then returns:

{
    "_id" : ObjectId("520cf82fd3541122f936f72e"),
    "pmhistory" : [
        {
            "sendername" : "Tati",
            "preview" : "Hey Man!",
            "last_updated" : 1376581408
        },
        {
            "sendername" : "Dan",
            "preview" : "Hey Moon!",
            "last_updated" : 1376581716876
        },
        {
            "sendername" : "Hellen",
            "preview" : "Hello, Im proper!",
            "last_updated" : 1376581508
        }
    ],
    "user" : ObjectId("520b842005ab0d0000000002"),
    "userid" : "1"
}

Then in your application, in the display part, just make sure your order by this new last_updated field descendingly.

Upvotes: 1

DhruvPathak
DhruvPathak

Reputation: 43235

You can use $push in conjunction with $slice to fix the array size and purge the last element.

http://docs.mongodb.org/manual/reference/operator/slice/

Upvotes: 0

Related Questions