简体   繁体   中英

PHP/MongoDB: update a value in an array

I have the following mongodb object:

{
   "_id": ObjectId("4d0b9c7a8b012fe287547157"),
   "messages": {
     "0": {
       "toUname": "Eamorr3",
       "fromUname": "Eamorr2",
       "time": 1292606586,
       "id": "ABCDZZZ",
       "subject": "asdf",
       "message": "asdf",
       "read": 0   //I want to change this to 1!
    },
    "1": {
       "toUname": "Eamorr1",
       "fromUname": "Eamorr3",
       "time": 1292606586,
       "id": "EFGHZZZ",
       "subject": "asdf2",
       "message": "asdf2",
       "read": 0
    }
  },
   "uname": "Eamorr3"
}

How do I set "read" to 1 where id=ABCDZZZZ? I'm using PHP.

I've tried the following command:

$driverInboxes->update(array('uname'=>$uname),array('$set'=>array('messages'=>array('id'=>$id,'read'=>'1'))));

But when I do this, overwriting occurs and I get:

{
   "_id": ObjectId("4d0b9c7a8b012fe287547157"),
   "messages": {
     "id": "j7zwr2hzx14d3sucmvp5",
     "read": "1"
  },
   "uname": "Eamorr3"
}

I'm totally stuck. Any help much appreciated.

Do I need to pull the entire array element, modify and and push it back in again?

Many thanks in advance,

If you read your command, you're actually saying: "UPDATE WHERE uname = Eamorr3 SET messages equal to this array (id=blah,read=1)"

When you do a $set on messages , you're basically instructing it to take your array as the new value.

However, it looks like you're trying to update a specific message as read which is just a little more complex. So there are two hurdles here:

1: You're actually updating messages.0.read

If you do array('$set' => array( 'messages.0.read' => 1 ) ) , you will update the correct element. Follow that chain, messages is a javascript object and you want to update the property 0 . The property 0 is itself a javascript object which contains the property read which you want to update.

Can you see how you're updating messages.0.read ?

This brings us to problem #2.

2: the 0 is a problem for you

If you look at the way you've structured the data in Mongo, the messages object is really sub-par. The "0" and "1" are currently acting as "ids" and they're not very useful. Personally, I would structure your objects with the actual IDs in place of "0" or "1".

So your objects would look like the following:

{
   "_id": ObjectId("4d0b9c7a8b012fe287547157"),
   "messages": {
     "ABCDZZZ": {
       "toUname": "Eamorr3",
       "fromUname": "Eamorr2",
       "time": 1292606586,
       "subject": "asdf",
       "message": "asdf",
       "read": 0   //I want to change this to 1!
    }
  },
   "uname": "Eamorr3"
}

Now you're update command becomes this:

array('$set' => array( 'messages.ABCDZZZ.read' => 1 ) )

This structure makes it much easier to update a specific message or a specific portion of a message.

If you want to keep the array structure for various purposes, you can use the Positional operator . This enables you to take advantage of array features ($pop,$push,etc) while simultaneously being able to update elements which are in an unknown array position.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM