更新MongoDB中的嵌入式文档详细信息

时间:2011-04-02 07:47:47

标签: c# mongodb

在MongoDB中,如果我有如下文档结构:

{ "_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" }

(即个人文档中嵌入了Person数组的Companies文档),然后如何使用单个查询更新特定公司的所有实例(通过公司_id进行定位)+更新

我尝试了以下内容:

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);

但它不起作用。我想我的问题归结为两个问题:如何在初始查询中定位嵌入式公司,然后如何在Set语句中设置新的公司名称。注意:在此示例中,我选择“非规范化”公司数据,并将其嵌入到每个人员文档中,因此可能存在具有相同公司ID和名称的多个人员文档。非常感谢。

更新: 使用Bugai13的技术我已经接近了。这有效:

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);

但这不起作用:

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);

所以,我还不能使用主键更新,这是我需要做的......

2 个答案:

答案 0 :(得分:9)

我想你应该看一下mongodb中的positional operator

var update = MongoDB.Driver.Builders.Update
                                 .Set("companies.$.name", "GreenfinNewName");
                                                 ^^
                                            all magic here

注意:上面的代码只会更新数组中匹配的first项。因此,如果您有两个嵌套数组的公司,上面有name = GreenfinNewName代码,则只会更新第一个匹配的。

注意:UpdateFlags.Multi表示多个文档,但不是嵌套数组中的多个项目。

<强>更新

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);

希望这有帮助!

答案 1 :(得分:0)

只想对你们两个表示感谢。我正在学习Mongo和这个主题的帮助。

我正在使用10gen C#驱动程序,作为参考,这是我的代码:

        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"]);
        }