In MongoDB, if I have a document structure as follows:
{ "_id" : { "$binary" : "jchPoPd7PUS1w+sR7is23w==", "$type" : "03" },
"companies" :
[
{ "_id" : { "$binary" : "jchPoPd7PUS1w+sR7is23w==", "$type" : "03" },
"name" : "Google" },
{ "_id" : { "$binary" : "jchPoPd7PUS1w+sR7is23w==", "$type" : "03" },
"name" : "Greenfin" },
{ "_id" : { "$binary" : "jchPoPd7PUS1w+sR7is23w==", "$type" : "03" },
"name" : "Zynet" }
],
"firstname" : "Peter",
"surname" : "Smith" }
(i.e. a Person
document with a Companies
array embedded within the person document), then how do I update ALL occurrences of a specific Company (targetting via the company _id) with a single query+update?
I have tried the following:
MongoCollection personCollection = mdb.GetCollection("person");
BsonBinaryData bin = new BsonBinaryData(new Guid("0AE91D6B-A8FA-4D0D-A94A-91D6AC9EE343"));
QueryComplete query = Query.EQ("companies._id", bin);
var update = Update.Set("companies.name", "GreenfinNewName");
SafeModeResult result = personCollection.Update(query, update, UpdateFlags.Multi);
but it doesn't work. I guess my question boils down to two questions: how do I target the embedded companies in the initial query, and then how do I set the new company name in the Set statement. Note: In this example I have chosen to "denormalise" the company data, and embed it in each person document, so there may be several person documents with the same company id and name. Thanks very much.
UPDATE: Using Bugai13's technique I've got closer. This works:
MongoCollection personCollection = mdb.GetCollection("person");
QueryComplete query = Query.EQ("companies.name", "Bluefin");
var update = Update.Set("companies.$.companynotes", "companynotes update via name worked");
SafeModeResult result = personCollection.Update(query, update, UpdateFlags.Multi, SafeMode.True);
But this doesn't work:
MongoCollection personCollection = mdb.GetCollection("person");
BsonBinaryData bin = new BsonBinaryData(new Guid("0AE91D6B-A8FA-4D0D-A94A-91D6AC9EE343"));
Builders.QueryComplete query = Query.EQ("companies._id", bin);
var update = Update.Set("companies.$.companynotes", "companynotes update via id worked");
SafeModeResult result = personCollection.Update(query, update, UpdateFlags.Multi, SafeMode.True);
So, I can't yet update using the primary key, which is what I need to do...
I suppose use you should take a look into positional operator in mongodb:
var update = MongoDB.Driver.Builders.Update
.Set("companies.$.name", "GreenfinNewName");
^^
all magic here
Note: above code will update only first
matched item in array. So if you have two company in nested array with name = GreenfinNewName
above code will update only first matched.
Note: UpdateFlags.Multi
means multiple documents, but not multiple items in nested array.
Update:
QueryComplete query = Query.EQ("companies._id",
BsonValue.Create(new Guid("0AE91D6B-A8FA-4D0D-A94A-91D6AC9EE343")));
var update = Update.Set("companies.$.companynotes", "companynotes");
personCollection.Update(query, update, UpdateFlags.Multi, SafeMode.True);
Hope this help!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With