61

I have the following doc stored in MongoDB:

{
    name: 'myDoc',
    list: [
        {
            id:1
            items:[
                {id:1, name:'item1'},
                {id:2, name:'item2'}
            ]
        },
        {
            id:2
            items:[
                {id:1, name:'item1'},
                {id:3, name:'item3'}
            ]
        }
    ]
}

I found a way to add an element to 'list' using $addToSet but I couldn't find a way to add to a specific list of 'items' an item.

e.g. I get the following:

{id:5, name:'item5'} 

and I want to add it to the element's item in the list with id:2.

Dhia
  • 10,119
  • 11
  • 58
  • 69
Guy Korland
  • 9,139
  • 14
  • 59
  • 106

2 Answers2

63

One way of doing it would be with $push:

db.col.update(
    { name: 'doc', 'list.id': 2 }, 
    {$push: {'list.$.items': {id: 5, name: 'item5'}}}
)

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

You can also replace $push with other operators like (possibly) $addToSet to get a similar result to what you are looking for. The main difference is that $push will append the new element to the list, whereas $addToSet will add the element if it is not there (a unique set of elements).

David Beauchemin
  • 231
  • 1
  • 2
  • 12
Sammaye
  • 43,242
  • 7
  • 104
  • 146
19

You can use this: -

> var toInsert = {id: 5, name: 'item6'}
> db.abc.update(
            { name: 'myDoc', list: { $elemMatch: { id: 2 } } },
            { $addToSet: { 'list.$.items': toInsert } }
  )

The query part will find the document from the list array with id = 2. Then we use $ positional element to add a new element at that array index.

See positional $ operator


You can also replace list: {$elemMatch: {id: 2}} with just 'list.id': 2.

But using $elemMatch will be better, when you want to update based on multiple elements of your array. For e.g., when your matching criteria is id and some another field in the array say length: -

list: {$elemMatch: {id: 2, length: 5}}
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • Footnote, schemas with nested embedded arrays are almost always going to cause problems later since not all operations on lower level elements are possible with the current query language. I'd avoid it. – Remon van Vliet Dec 21 '12 at 14:38