我有一个深层嵌套的文档结构,如下所示:
{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}]
},
]
}
]
},
]
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试更新集合以插入新的配置,如下所示:
newdata = {
config: "Custom 1",
variables: [{ x: 111, y:2222, z:3333}]
}
Run Code Online (Sandbox Code Playgroud)
我在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}}
)
Run Code Online (Sandbox Code Playgroud)
我得到"无法应用位置运算符而没有包含数组的相应查询字段"错误.在mongo中执行此操作的正确方法是什么?这是mongo v2.4.1.
Joh*_*yHK 47
遗憾的是,$每个键不能多次使用运算符,因此必须使用其余的数值.如:
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}}
)
Run Code Online (Sandbox Code Playgroud)
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}]
},
]
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以用以下方法更新它:
db.myCollection.update({
_id: 123,
'levels.proven.configs.config': 'Custom 1'
},
{ $set: { 'levels.proven.configs.$': newData }}
)
Run Code Online (Sandbox Code Playgroud)
小智 18
管理使用猫鼬解决它:
您需要知道的是链中所有子文档的'_id'(mongoose为每个子文档自动创建'_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();
});
Run Code Online (Sandbox Code Playgroud)
有关mongoose文档中的子文档_id方法的更多信息.
解释:_id用于SchemaName,_id1用于sub1,_id2用于sub2 - 你可以保持链接.
*你不必使用findById方法,但在我看来这是最方便的,因为你需要知道'_id的其余部分.
NIK*_*C M 12
MongoDB引入了ArrayFilters来解决版本3.5.2及更高版本中的这个问题.
版本3.6中的新功能.
从MongoDB 3.6开始,在更新数组字段时,您可以指定arrayFilters来确定要更新的数组元素.
让我们说Schema设计如下:
var ProfileSchema = new Schema({
name: String,
albums: [{
tour_name: String,
images: [{
title: String,
image: String
}]
}]
});
Run Code Online (Sandbox Code Playgroud)
创建的文档如下所示:
{
"_id": "1",
"albums": [{
"images": [
{
"title": "t1",
"url": "url1"
},
{
"title": "t2",
"url": "url2"
}
],
"tour_name": "london-trip"
},
{
"images": [.........]:
}]
}
Run Code Online (Sandbox Code Playgroud)
说我想更新图像的"网址".鉴于 - "document id", "tour_name" and "title"
为此更新查询:
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');
})
Run Code Online (Sandbox Code Playgroud)
我今天面临同样的问题,经过在 google/stackoverflow/github 上的大量探索,我认为这arrayFilters是解决这个问题的最佳方法。这适用于 mongo 3.6 及更高版本。这个链接终于救了我的一天:https : //thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-array-filters.html
const OrganizationInformationSchema = mongoose.Schema({
user: {
_id: String,
name: String
},
organizations: [{
name: {
type: String,
unique: true,
sparse: true
},
rosters: [{
name: {
type: String
},
designation: {
type: String
}
}]
}]
}, {
timestamps: true
});
Run Code Online (Sandbox Code Playgroud)
并在 express 中使用猫鼬,更新给定 id 的花名册名称。
const mongoose = require('mongoose');
const ControllerModel = require('../models/organizations.model.js');
module.exports = {
// Find one record from database and update.
findOneRosterAndUpdate: (req, res, next) => {
ControllerModel.updateOne({}, {
$set: {
"organizations.$[].rosters.$[i].name": req.body.name
}
}, {
arrayFilters: [
{ "i._id": mongoose.Types.ObjectId(req.params.id) }
]
}).then(response => {
res.send(response);
}).catch(err => {
res.status(500).send({
message: "Failed! record cannot be updated.",
err
});
});
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
60885 次 |
| 最近记录: |