0

I have a collection (favorites) with documents that look like this:

{
    "_id" : 907,
    "pictures" : [
        {
        "id" : 107,
        "url" : "http://url1",
        "title" : "some title"
        },
        {
        "id" : 111,
        "url" : "http://url2",
        "title" : "some other title"
        }
    ]
}

It's fairly easy to get just the urls using pictures.url.

But how do I update the url for all users that saved the picture with an id=111 as their favorite?

I found an work-around using:

107:['id':107,'url':'http://url1','title':'some title']

...and then using find() with pictures.107.id => 107, but that looks silly to me.

Is there a better way to achieve this?

3
  • Which URL do you want to update? The one for 107 or 111? Or both? Commented Mar 27, 2012 at 13:29
  • doesn't matter , really, I am just looking to see if there's a better way of doing multiple updates, without relying on the workaround I mentioned (basically storing the picture_id twice), and hopefully still preserving the pictures.url in find(). with the workaround I am forced to get from mongo all fields in pictures Commented Mar 27, 2012 at 13:33
  • I posted an answer but given the other replies I may not have understood your original question (which, frankly, is a little unclear). What exactly is it you need to do? Just update all "url" values for all users that have 111 as their favorite? Commented Mar 27, 2012 at 14:22

2 Answers 2

3

Not entirely sure what you're looking for, but I'll give it a shot.

In MongoDB, you can do atomic updates with the $set operator, which will replace only the data you pass and not the whole document.

If you use it with the $elemMatch operator when selecting, you can update only the url of the pictures that match your query:

$mongo->selectCollection('mydb', 'favorites')
      ->update(
           array('pictures' => array(
               '$elemMatch' => array('id' => 107),
           )),
           array('$set' => array('pictures.$.url' => 'http://foobar'))
        );

You can see that the update contains pictures.$.url, where the $ refers to the element(s) that matched the $elemMatch query.

The above will update all the pictures.url in your favorites that match 111 as their pictures.id, giving you something like:

{ "_id" : 907, "pictures" : [
    {
        "id" : 107,
        "url" : "http://url1",
        "title" : "some title"
    },
    {
        "id" : 111,
        "title" : "some other title",
        "url" : "http://foobar" // only this one has matched
    }
] }
Sign up to request clarification or add additional context in comments.

1 Comment

thanks, as it turns out, the solution was very simple - ($elemMatch)
1
db.favorites.update({pictures: {$elemMatch:{id:111}}}, {'pictures.$.title':"Some Title"}, false, true)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.