Howto MongoDB update / $set entire subdocument

In my MongoDB, I have Document1, as seen below. I want to reach into the "main.accounts" (and later, "main.entries") document, and update ($set) an entire sub-document in a "content' array. Wrt sub-documents, so far, I've been able to add and remove a document to and from a "content" sub-array. But in this case, I want to update the entire document; Not just update ($set) one property in a matched document.

Below, I've tried using just a $set, a $set with $elemMatch. And I've also tried findAndModify, but to no avail. Of course, I've i) RTFM, looked all around ii) the internet and iii) SO, to find a solution. Has anyone been able to update an entire document in this manner?

Thanks Tim

Update try 1 - this is the only update that works, but sets the entire "content" array to the hash … { "fu" : "bar" }


    db.bookkeeping.update(
      { 
        owner : "twashing@gmail.com", 
        "content.content.tag" : "account", 
        "content.content.id" : "one" 
      }, 
      { $set : { "content.$.content" : { "fu" : "bar" } } } 
    )

Update try 2 - this doesn't fail, but doesn't update the document in question


    db.bookkeeping.update(
      { 
        owner : "fu", 
        thing : { $elemMatch : { "content.content.tag" : "account", "content.content.id" : "one"  } }
      }, 
      { $set : { "thing" : { "fu" : "bar" } } } 
    )

Update try 3 - this doesn't fail, but doesn't update the document in question


    db.bookkeeping.update(
      { thing : { $elemMatch : { owner : "fu" ,  "content.content.tag" : "account", "content.content.id" : "one" } } }, 
      { $set : { "thing.content.content.$" :  { "fu" : "bar" } } }
    )

Document1


    {
            "_id" : "fid",
            "content" : [
                    {
                            "content" : [
                                    {
                                            "id" : "one",
                                            "tag" : "account"
                                    },
                                    {
                                            "id" : "two",
                                            "tag" : "account"
                                    },
                                    {
                                            "id" : "three",
                                            "tag" : "account"
                                    },
                                    {
                                            "id" : "four",
                                            "tag" : "account"
                                    },
                                    {
                                            "id" : "five",
                                            "tag" : "account"
                                    }

                            ],
                            "id" : "main.accounts",
                            "tag" : "accounts"
                    },
                    {
                            "tag" : "journals",
                            "id" : "main.journals",
                            "content" : [
                                    {
                                            "tag" : "journal",
                                            "id" : "generalledger",
                                            "name" : "generalledger",
                                            "type" : "",
                                            "balance" : "",
                                            "content" : [
                                                    {
                                                            "tag" : "entries",
                                                            "id" : "main.entries",
                                                            "content" : [ ]
                                                    }
                                            ]
                                    }
                            ]
                    }
            ],
            "owner" : "fu",
            "tag" : "fubar"
    }

Answers


You won't be able to use positional operator $ for updating second level of array.(Array inside array)

This link might help you


I believe you can't do that in the mongoDB console without some programming logic, because you use multiple arrays in your structure and you are searching for an sub document (content[documents]) (main.accounts and main.entries) in an array, which will return the same root document, but in that return value you can not know on what position in the content array was your criteria. Because of that you can't inject your new values at the right position.

If possible I would recommend to restructure the document to avoid so many nested arrays(content->content->content->content), especially if you plan to do some updates on subset of them. After all this is NoSQL so its' fine to have some redundant data in your design, as long that makes your life easier and your code more clean.


Need Your Help

Pass or Get a value from Parent ViewModel down to Sub-ViewModel?

xaml mvvm nested viewmodel mvvm-light

I am using the MVVM Light framework as well as Unity for DI. I have some nested Views, each bound to a corresponding ViewModel. The ViewModels are bound to each View's root control DataContext via ...

How to parse untagged pdf file with iText

java pdf itext pdf-parsing

I want to parse this file (http://www.bbm.ca/_documents/top_30_tv_programs_english/2011/nat01032011.pdf) with iText. The problem is it is not tagged so I can't get the XML file. I decided to extrac...