无法将数组回填到大于1500000个元素

时间:2014-08-18 13:43:34

标签: javascript node.js mongodb mongoose

我有一个名为collection的mongodb文档:

{
    _id: ObjectId('53e9dd54c784717558c46997'),
    bloks: [ /* subdocument array */ ],
    sections: [ /* subdocument array */ ],
    chapters: [ /* subdocument array */ ]
} 

并且每个子文档都有idstate个字段作为其他字段之间的字符串。

使用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()方法执行实际保存时遇到问题。

2 个答案:

答案 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'
});

此方法的唯一问题是您无法使用单个查询更新多个子文档。因此,它需要两个请求来更新sectionschapters


您还应该考虑使用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来确保子文档数组中的文档顺序没有改变,从而保护您不会更新错误的子文档。