当前位置: 首页 > 知识库问答 >
问题:

Mongodb更新深度嵌套子文档

公西运良
2023-03-14

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

{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}]
                            }, 
                    ]
                }
            ]
        }, 
    ]

}

我正在尝试更新集合以插入新配置,如下所示:

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.

共有3个答案

陶元凯
2023-03-14

MongoDB在版本3.5.2及更高版本中引入了ArrayFilters来解决这个问题。

新版本3.6。

从MongoDB 3.6开始,在更新数组字段时,可以指定确定要更新哪些数组元素的ArrayFilter。

[https://docs.mongodb.com/manual/reference/method/db.collection.update/#specify-用于阵列更新操作的ArrayFilter][1]

假设模式设计如下所示:

var ProfileSchema = new Schema({
    name: String,
    albums: [{
        tour_name: String,
        images: [{
            title: String,
            image: String
        }]
    }]
});

创建的文档如下所示:

{
   "_id": "1",
   "albums": [{
            "images": [
               {
                  "title": "t1",
                  "url": "url1"
               },
               {
                  "title": "t2",
                  "url": "url2"
               }
            ],
            "tour_name": "london-trip"
         },
         {
            "images": [.........]: 
         }]
}

假设我想更新图像的“url”。给定-“文档id”、“巡演名称”和“标题”

为此,请执行更新查询:

Profiles.update({_id : req.body.id},
    {
        $set: {

            'albums.$[i].images.$[j].title': req.body.new_name
        }
    },
    {
        arrayFilters: [
            {
                "i.tour_name": req.body.tour_name, "j.image": req.body.new_name   // tour_name -  current tour name,  new_name - new tour name 
            }]
    })
    .then(function (resp) {
        console.log(resp)
        res.json({status: 'success', resp});
    }).catch(function (err) {
    console.log(err);
    res.status(500).json('Failed');
})
王凌
2023-03-14

使用mongoose解决了这个问题:

您只需要知道链中所有子文档的_id(猫鼬会自动为每个子文档创建_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();
  });

更多关于猫鼬留档中的子文档_id方法。

说明:_id代表SchemaName,_id1代表sub1,_id2代表sub2-您可以这样继续链接。

*您不必使用findById方法,但在我看来这是最方便的,因为您需要知道其余的'\u id'。

姬熙云
2023-03-14

不幸的是,您不能在每个键上使用$运算符一次以上,因此您必须在其余部分使用数值。如在:

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对更新嵌套数组的支持很差。因此,如果需要频繁地更新数据,那么最好避免使用它们,而应考虑使用多个集合。

一种可能性是:将forecast设置为自己的集合,并假设您有一组固定的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 }}
)
 类似资料:
  • 我想在具有指定 URL 的相应文档中将嵌套的“已爬行”更新为 True。 我对mongodb相当陌生,我似乎无法弄清楚这一点,非常感谢任何帮助。

  • 我的mongoDB记录就像在这个链接更新嵌套数组mongob和示例记录如下,想要更新嵌套文档“参数”数组中的一个字段,前提是它满足一些条件(_id:“04”,操作。_id:“100”和operations.parameters.pid:“012”),此更新查询UPDATES错误嵌套记录(operations.parameters.pid:“011”),请帮助我哪里出错了: 我的更新查询如下: 我使

  • 我正在尝试更新嵌套数组中的值,但无法使其工作。 我的对象是这样的 提前谢谢!

  • 本文向大家介绍MongoDB查询中如何更新嵌套文档,包括了MongoDB查询中如何更新嵌套文档的使用技巧和注意事项,需要的朋友参考一下 要更新嵌套文档,请使用update(),并在其中使用点号。让我们创建一个包含文档的集合- 在find()方法的帮助下显示集合中的所有文档- 这将产生以下输出- 以下是更新嵌套文档的查询- 在find()方法的帮助下显示集合中的所有文档- 这将产生以下输出-

  • 问题内容: 我正在寻找一种使用dict update内容更新dict dictionary1的方法 我知道update会删除level2中的值,因为它正在更新最低的密钥level1。 鉴于dictionary1和update可以有任何长度,我该如何解决? 问题答案: @FM的答案具有正确的总体思路,即递归解决方案,但有些特殊的编码和至少一个错误。我建议改为: Python 2: Python 3:

  • 我正在使用平均堆栈在网格中显示以下数组。 嵌套数组: