开发者

Update embedded document details in MongoDB

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 up开发者_运维知识库date 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!


Just wanted to say thanks to you both. Am learning Mongo and this thread helped.

I'm using the 10gen C# driver, and for reference this is my code:

        MongoServer mongo = MongoServer.Create();

        MongoDatabase db = mongo.GetDatabase("test");

        MongoCollection<BsonDocument> coll = db["contacts"];

        BsonDocument doc = new BsonDocument();

        doc["FirstName"] = "Daniel";
        doc["LastName"] = "Smith";
        doc["Address"] = "999 Letsby Avenue";
        doc["City"] = "London";
        doc["County"] = "Greater London";
        doc["Postcode"] = "N13";

        coll.Insert<BsonDocument>(doc);

        QueryComplete qSel = Query.EQ("Postcode", "N13");

        MongoCursor<BsonDocument> cur = coll.Find(qSel);
        foreach (BsonDocument bdoc in cur)
        {
            Console.WriteLine(bdoc["FirstName"] + ":" + bdoc["Address"]);
        }


        UpdateBuilder docTwo = Update.Set("Postcode", "MK10");

        coll.Update(qSel, docTwo, UpdateFlags.Multi);

        QueryDocument qSel2 = new QueryDocument("FirstName", "Daniel");

        MongoCursor<BsonDocument> cur2 = coll.Find(qSel2);
        foreach (BsonDocument bsdoc in cur2)
        {
            Console.WriteLine(bsdoc["FirstName"] + " : " + bsdoc["Postcode"]);
        }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜