Mongodb更新深度嵌套的子文档

我有一个深度嵌套的文档结构,如下所示:

{id: 1, forecasts: [ { forecast_id: 123, name: "Forecast 1", levels: [ { level: "proven", configs: [ { config: "Custom 1", variables: [{ x: 1, y:2, z:3}] }, { config: "Custom 2", variables: [{ x: 10, y:20, z:30}] }, ] }, { level: "likely", configs: [ { config: "Custom 1", variables: [{ x: 1, y:2, z:3}] }, { config: "Custom 2", variables: [{ x: 10, y:20, z:30}] }, ] } ] }, ] } 

我试图更新集合来插入一个新的configuration,如下所示:

 newdata = { config: "Custom 1", variables: [{ x: 111, y:2222, z:3333}] } 

我正在用mongo(Python)尝试这样的东西:

 db.myCollection.update({"id": 1, "forecasts.forecast-id": 123, "forecasts.levels.level": "proven", "forecasts.levels.configs.config": "Custom 1" }, {"$set": {"forecasts.$.levels.$.configs.$": newData}} ) 

虽然我得到“不能应用位置运算符没有包含数组相应的查询字段”错误。 在Mongo中这样做的正确方法是什么? 这是mongo v2.4.1。

不幸的是,你不能每个键使用多于一次的$操作符,所以你必须使用数字值。 如:

 db.myCollection.update({ "id": 1, "forecasts.forecast-id": 123, "forecasts.levels.level": "proven", "forecasts.levels.configs.config": "Custom 1" }, {"$set": {"forecasts.$.levels.0.configs.0": newData}} ) 

MongoDB对更新嵌套数组的支持很差。 因此,如果您需要经常更新数据,最好避免使用它们,而应考虑使用多个集合。

一种可能性: forecasts它自己的集合,并假设你有一个固定的一组level值,使level对象而不是数组:

 { _id: 123, parentId: 1, name: "Forecast 1", levels: { proven: { configs: [ { config: "Custom 1", variables: [{ x: 1, y:2, z:3}] }, { config: "Custom 2", variables: [{ x: 10, y:20, z:30}] }, ] }, likely: { configs: [ { config: "Custom 1", variables: [{ x: 1, y:2, z:3}] }, { config: "Custom 2", variables: [{ x: 10, y:20, z:30}] }, ] } } } 

然后你可以使用以下方式更新

 db.myCollection.update({ _id: 123, 'levels.proven.configs.config': 'Custom 1' }, { $set: { 'levels.proven.configs.$': newData }} ) 

pipe理解决它与mongoose:

所有你需要知道的是链中所有子文档的'_id'(mongoose为每个子文档自动创build'_id')。

例如 –

  SchemaName.findById(_id, function (e, data) { if (e) console.log(e); data.sub1.id(_id1).sub2.id(_id2).field = req.body.something; // or if you want to change more then one field - //=> var t = data.sub1.id(_id1).sub2.id(_id2); //=> t.field = req.body.something; data.save(); }); 

关于mongoose文档中的子文档_id方法的更多信息。

解释:_id是SchemaName,_id1是sub1,_id2是sub2 – 你可以像这样保持链接。

*您不必使用findById方法,但是在我看来,这是最方便的,因为无论如何您需要知道其余的_id。

这是MongoDB中的一个非常老的错误

https://jira.mongodb.org/browse/SERVER-831

鉴于MongoDB似乎没有提供一个好的机制,我发现使用mongoose简单地使用.findOne(...)从mongo集合中提取元素,在其相关的子元素上执行for-loopsearch(通过ObjectID查找),修改该JSON,然后执行Schema.markModified('your.subdocument'); Schema.save(); Schema.markModified('your.subdocument'); Schema.save(); 这可能效率不高,但它非常简单,工作正常。

这是固定的。 https://jira.mongodb.org/browse/SERVER-831

但是这个特性是从MongoDB 3.5.12开发版本开始的。

注意:这个问题在Aug 11 2013Aug 11 2013提出,并在Aug 11 2017Aug 11 2017解决

Okkk.we可以更新我们在mongodb中的嵌套子文档。这是我们的模式。

 var Post = new mongoose.Schema({ name:String, post:[{ like:String, comment:[{ date:String, username:String, detail:{ time:String, day:String } }] }] }) 

解决scheme

  Test.update({"post._id":"58206a6aa7b5b99e32b7eb58"}, {$set:{"post.$.comment.0.detail.time":"aajtk"}}, function(err,data){ //data is updated }) 

分享我的经验教训。 我最近遇到了同样的需求,我需要更新一个嵌套的数组项目。 我的结构如下

  { "main": { "id": "ID_001", "name": "Fred flinstone Inc" }, "types": [ { "typeId": "TYPE1", "locations": [ { "name": "Sydney", "units": [ { "unitId": "PHG_BTG1" } ] }, { "name": "Brisbane", "units": [ { "unitId": "PHG_KTN1" }, { "unitId": "PHG_KTN2" } ] } ] } ] } 

我的要求是添加一些特定单位的字段[]。 我的解决scheme是首先find嵌套数组项目的索引(比如foundUnitIdx)我使用的两种技术是

  1. 使用$ set关键字
  2. 使用[]语法指定$ set中的dynamic字段

      query = { "locations.units.unitId": "PHG_KTN2" }; var updateItem = { $set: { ["locations.$.units."+ foundUnitIdx]: unitItem } }; var result = collection.update( query, updateItem, { upsert: true } ); 

希望这可以帮助别人。 🙂