Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I replace an entire array of subdocuments in MongoDB?

Here is an example document from my collection:

Books
[
   id: 1,
   links:
   [
     {text: "ABC", "url": "www.abc.com"},
     {text: "XYZ", "url": "www.xyz.com"}
   ]
]

I want to replace the links array in one update operation. Here is an example of how the above document should be modified:

Books
[
   id: 1,
   links:
   [
     {text: "XYZ", "url": "www.xyz.com"},
     {text: "efg", "url": "www.efg.com"},   <== NEW COPY OF THE ARRAY
     {text: "ijk", "url": "www.ijk.com"}
   ]
]

As you can see, the links array has been replaced (old data removed, and new data added).

I am having very hard time with the Update.Set() because it says it MyLinks<> cannot be mapped to a BsonValue

I've tried many different ways of achieving this, and all of them fail, including .PushAllWrapped<WebLinkRoot>("links", myDoc.WebLinks). Everything I've tried results in the new values being appended to the array, rather than the array being replaced.

As it seems MongoDB doesn't provide a simple method to replace an array of subdocument OR a method like .ClearArray(), what is the best way for me to ensure the array is cleared before adding new elements in a single query?

like image 394
kheya Avatar asked Mar 06 '14 02:03

kheya


People also ask

How do I update an array of documents in MongoDB?

You can use the updateOne() or updateMany() methods to add, update, or remove array elements based on the specified criteria. It is recommended to use the updateMany() method to update multiple arrays in a collection.

How do I replace a whole document in MongoDB?

In MongoDB, you are allowed to replace an existing document with a new document in the collection with the help of db. collection. replaceOne() method. This method will replace the existing document with the replacement document.

How do I update a nested array in MongoDB?

Update Nested Arrays in Conjunction with $[]The $[<identifier>] filtered positional operator, in conjunction with the $[] all positional operator, can be used to update nested arrays. The following updates the values that are greater than or equal to 8 in the nested grades.


2 Answers

I am here because I saw 5k views on this post, I'm adding some stuff may be it help other who looking for answer of above

 db.collectionName.insertOne({
      'links': [
                 {
                     "text" : "XYZ",
                      "url" : "www.xyz.com"
                  }
        ]
  });

now run this query which help to replace older data

db.collectionName.update(
      {
        _id: ObjectId("your object Id")
      }, 
      {
        $set: 
         {
          'links':[ {
                     "text" : "XYZ1",
                     "url" : "www.xyz.com1"
                   } ]
         }
      });
like image 176
Abhishek Singh Avatar answered Nov 12 '22 01:11

Abhishek Singh


I think you have to do something like this:

var newArray = new BSONArray {
    new BSONDocument { { "text", "XYZ" }, { "url", "www.xyz.com" } },
    new BSONDocument { { "text", "efg" }, { "url", "www.efg.com" } },
    new BSONDocument { { "text", "ijk" }, { "url", "www.ijk.com" } }
};

var update = Update.Set( "links", newArray );

collection.Update( query, update );

Or whatever method you can to cast as a valid BSONValue.

So equivalent to shell:

{ "links" : [ { "text" : "abc" } ] }

> db.collection.update(
      {},
      { $set: 
          { links: [ 
              { text: "xyz", url: "something" },
              { text: "zzz", url: "else" }
          ]}
      })

>db.collection.find({},{ _id: 0, links:1 }).pretty()

{ "links" : [
            {
                    "text" : "xyz",
                    "url" : "something"
            },
            {
                    "text" : "zzz",
                    "url" : "else"
            }
    ]
}

So that works.

You clearly need something else other than embedded code. But hopefully that puts you on the right track.

like image 35
Neil Lunn Avatar answered Nov 11 '22 23:11

Neil Lunn