【问题标题】:Update embedded document details in MongoDB更新 MongoDB 中的嵌入文档详细信息
【发布时间】:2011-07-28 04:10:30
【问题描述】:

在 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" }

(即在个人文档中嵌入Companies 数组的Person 文档),那么我如何通过单个查询+更新更新所有出现的特定公司(通过公司_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);

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

【问题讨论】:

    标签: c# mongodb


    【解决方案1】:

    只是想对你们俩说声谢谢。正在学习 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"]);
            }
    

    【讨论】:

      【解决方案2】:

      我想你应该看看 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);
      

      希望对您有所帮助!

      【讨论】:

      • 非常感谢,这让我更接近了。使用您的技术允许我根据数组中的文本值进行更新,而不是根据主 _id 键。我会用细节更新问题...
      • 非常抱歉,刚刚注意到用于构建嵌套密钥的逻辑错误。已调整,现在一切正常。非常感谢您的帮助,很抱歉今天早上浪费了您的时间。
      • @JohnNorris:没问题,我还添加了正确答案,mb这对某人有用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      • 2016-06-17
      • 2014-03-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多