Question

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?

Was it helpful?

Solution 2

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.

OTHER TIPS

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"
                   } ]
         }
      });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top