我有一个名为collection的mongodb文档:
{
_id: ObjectId('53e9dd54c784717558c46997'),
bloks: [ /* subdocument array */ ],
sections: [ /* subdocument array */ ],
chapters: [ /* subdocument array */ ]
}
并且每个子文档都有id
和state
个字段作为其他字段之间的字符串。
使用mongoose时,我可以更新bloks
并使用以下命令返回集合:
update = { bloks: [ /*some changed array*/ ] };
Collection.findByIdAndUpdate(collection._id, update, function (err, collection) {
if (err) {
// return an error
} else {
// return the collection
}
});
但是当我尝试更新其他数组中的特定部分和章节状态时:
update = {
bloks: [ /*some changed array*/ ],
'sections.140439739188823467.state': 'some state',
'chapters.1404397391757313579.state': 'some state'
};
我收到错误:
Can't backfill array to larger than 1500000 elements
如何使用bloks,section和chapter数据更新集合文档并使其具有当前值?
请注意,我正在使用.findByIdAndUpdate()
,因为它更有效率,并且我在使.update()
方法执行实际保存时遇到问题。
答案 0 :(得分:0)
感谢Leonid Beschastny在问题中的评论,我发现我使用子文档ID作为数组中的索引,所以我修改了代码以找出正确的代码。
sindex = _.findIndex(collection.sections, function (section) {
return sid === section.id;
});
if (-1 < sindex) {
update['sections.' + sindex + '.state'] = 'state';
}
hindex = _.findIndex(collection.chapters, function (chapter) {
return hid === chapter.id;
});
if (-1 < hindex) {
update['chapters.' + hindex + '.state'] = 'state';
}
答案 1 :(得分:0)
实际上,有一种方法可以使用positional operator $
更新子文档的字段ID:
db.collection.update({
_id: collection._id,
'sections.id': '140439739188823467'
}, {
'sections.$.state': 'some state'
});
此方法的唯一问题是您无法使用单个查询更新多个子文档。因此,它需要两个请求来更新sections
和chapters
。
您还应该考虑使用mongoose
Sub Docs feature。您现有架构中唯一需要更改的是子文档的主要ID字段,因为mongoose
始终使用_id
字段作为主要标识符。
它允许您使用MongooseDocumentArray::id
helper,专为您的情况设计:
sindex = collection.sections.id(sid);
hindex = collection.sections.id(hid);
另一件事。
由于您已经提取了自己的文档,因此无需发出findAndModify
操作,因为当您在.save()
文档上调用mongoose
方法时,它会发出update
1}}操作,只向更新的字段发送到MongoDB:
collcetion[sindex].state = 'new state';
collcetion[hindex].state = 'new state';
collcetion.save(next);
// Mongoose sends update operation, setting only this two fields
此外,mongoose正在使用versioning来确保子文档数组中的文档顺序没有改变,从而保护您不会更新错误的子文档。