19

I have collection with a document like this:

{
    _id : "abcd",
    name : "Tom",
    myArray : [
        {
            field1 : "",
            field2 : ""
        }
    ]
},
{
    _id : "efgh",
    name : "Jerry"
}

I have a new object for myArray. I want to write a query to update only one document.

If the query matches the document with _id : "abcd", then push the new object in to myArray field:

{
    _id : "abcd",
    name : "Tom",
    myArray : [
        {
            field1 : "",
            field2 : ""
        },
        {
            // new object
        }
    ]
}

And if the query matches with _id : "efgh" create the field myArray with new object inside it:

{
    _id : "efgh",
    name : "Jerry"
    myArray : [
         {
              // new object
         }
    ]
}

How can I achieve this?

5
  • What do you want to do? Set "myArray" in "efgh" to the same content as "abcd"? Or do you want to push a new array item to both "abcd" and "efgh"? There is an Edit link on your question where you can add details to make your intentions clear. Commented Aug 2, 2015 at 9:41
  • @BlakesSeven , modified question hope you understand... Commented Aug 2, 2015 at 9:56
  • Still unclear what you mean by "elseif" here. Do you mean to update "both" documents, or are you only selecting to update "one" of the documents? Commented Aug 2, 2015 at 10:04
  • No i don't want to update both document. Update only one document at a time. Commented Aug 2, 2015 at 10:10
  • Have you even tried anything here? I'm guessing not because you would see what happens when you $push an array to a document where it does not exist is that it just creates the array. Where there is an existing array the then new document is appended. So either you have not tried at all or there is still something missing from your question about what you really want to do. Commented Aug 2, 2015 at 10:14

2 Answers 2

35

To explain all the possible cases here, the consider each document case:

If your document to alter looks like this:

{
    "_id": "efgh",
    "name": "Jerry"
}

Then an update statment like this:

db.collection.update(
    { "_id": "efgh" },
    { "$push": { "myArray": { "field1": "abc", "field2": "def" } } }
)

Results in this:

{
    "_id": "efgh",
    "name": "Jerry",
    "myArray": [
        {
            "field1": "abc",
            "field2": "def"
        }
    ]
}

So the array is created and the new item appended.

If your document already has an array like this:

{
    "_id": "abcd",
    "name": "Tom",
    "myArray": [
        {
            "field1": "",
            "field2": ""
        }
    ]
}

And you do basically the same statement:

db.collection.update(
    { "_id": "abcd" },
    { "$push": { "myArray": { "field1": "abc", "field2": "def" } } }
)

Then the new document content is appended to the existing array:

{
    "_id": "abcd",
    "name": "Tom",
    "myArray": [
        {
            "field1": "",
            "field2": ""
        },
        {
            "field1": "abc",
            "field2": "def"
        }
    ]
}

If however your original document has the named field but it is not an array, like this:

{
    "_id": "efgh",
    "name": "Jerry",
    "myArray": 123
}

Then make sure it is not an array by testing in the query condtion and using $set instead:

db.collection.update(
    { "_id": "efgh", "myArray.0": { "$exists": false } },
    { "$set": { "myArray": [{ "field1": "abc", "field2": "def" }] } }
)

That will safely overwrite the element that is not an array ( dot notation "myArray.0" means first array element, which is not true ) with a new array containing your content. The result is the same as the original:

{
    "_id": "efgh",
    "name": "Jerry",
    "myArray": [
        {
            "field1": "abc",
            "field2": "def"
        }
    ]
}
Sign up to request clarification or add additional context in comments.

1 Comment

instead of $push can you used $addToSet and will it check that the array doesn't contain the exact same json document?
5

$Push is what you need to achieve this. If the myArray is already existing then $push will insert the newObject to it( similar to the STACK data structure operation ). If the myArray doesn't exist, it will create the field "myArray" as key and will insert the newObject into it ( similar to $Set oprtaion )

Consider another below sample document :

{
_id : "abcd"
myArray:[
{
  field1:"mango",
  field2:"apple"
}
       ]
}

so now lets Insert the below object to it :

var newObject = {field1:"example1" , field2:"exmaple2"};

Query :

db.collection.update({_id:"abcd"},{"$push":{myArray: newObject }});

after execution of the above query, result is as below :

{
    _id : "abcd"
    myArray:[
    {
      field1:"mango",
      field2:"apple"
    },
    {
      field1:"example1" , 
      field2:"exmaple2"
    }
           ]
    }

Now let us consider another example where "myArray" key is NOT PRESENT in the document :

{
_id:"efg"
}

so lets insert the below object :

 var newObject2 = { field1 : "exp2" , field2 : "exp1" }

Query :

 db.collection.update({_id:"efg"},{"$push":{myArray: newObject2 }});

Result of the above UPDATE operation is below :

 {
   _id : "efg"
   myArray : [ 
   { 
    field1 : "exp2" , 
    field2 : "exp1"
  }
          ]
}

2 Comments

what if we want to add a new document itself if not document with that id is not available ?.
@Rahul_Dabhi Did you find an answer to your question? I want to be able to do that.

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.