简体   繁体   English

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

[英]Can't backfill array to larger than 1500000 elements

I have a mongodb document named collection: 我有一个名为collection的mongodb文档:

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

and each of the subdocuments have id and state fields as strings among some other fields. 每个子文档在其他字段中都有idstate字段作为字符串。

When using mongoose, I can update the bloks and return the collection using: 当使用猫鼬,我可以更新bloks并使用返回集合:

update = { bloks: [ /*some changed array*/ ] };

Collection.findByIdAndUpdate(collection._id, update, function (err, collection) {
    if (err) {
        // return an error
    } else {
       // return the collection
    }
});

But when I try to update also a specific section and chapter state in the other arrays: 但是当我尝试更新其他数组中的特定节和章状态时:

update = { 
    bloks: [ /*some changed array*/ ],
    'sections.140439739188823467.state': 'some state',
    'chapters.1404397391757313579.state': 'some state'
};

I get an error: 我收到一个错误:

Can't backfill array to larger than 1500000 elements

How can I update the collection document with the bloks, sections and chapters data and have it's current value? 如何使用空白,章节和章数据更新收集文档并具有当前值?

Please note, I'm using .findByIdAndUpdate() because it is more efficient and I had problems making the .update() method do the actual save. 请注意,我使用的是.findByIdAndUpdate()因为它效率更高,而且在使.update()方法执行实际保存时遇到问题。

Thanks to Leonid Beschastny comment in the question, I figured out that I was using the subdocuments IDs as indices in the arrays, so I modifed the code to figure out the correct ones. 多亏了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';
    }

Actually, there is a way to update sub-document's field by its id, using positional operator $ : 实际上,有一种方法可以使用位置运算符$通过子ID来更新子文档的字段:

db.collection.update({
    _id: collection._id,
    'sections.id': '140439739188823467'
}, {
    'sections.$.state': 'some state'
});

The only problem with this approach is that you can't update multiple sub-documents using single query. 这种方法的唯一问题是,您不能使用单个查询来更新多个子文档。 So, it'll require two requests to update both sections and chapters . 因此,将需要两个请求来更新sectionschapters


You should also consider using mongoose Sub Docs feature . 您还应该考虑使用mongoose Sub Docs功能 The only thing you'll need to change in your existing schema is the primary id field of you sub docs, because mongoose always use _id field as a primary identifier. 您在现有架构中唯一需要更改的是子文档的primary id字段,因为mongoose始终使用_id字段作为主要标识符。

It'll allow you to use MongooseDocumentArray::id helper , especially designed for your case: 它将允许您使用MongooseDocumentArray::id helper ,特别为您的案例设计:

sindex = collection.sections.id(sid);
hindex = collection.sections.id(hid);

And another thing. 还有一件事。

Since you're already fetching your document, there is no need for you to issue an findAndModify operation, because when you call .save() method on mongoose document it issues an update operation, sending to MongoDB only updated fields: 由于您已经在获取文档,因此无需执行findAndModify操作,因为在mongoose文档上调用.save()方法时,它将发出update操作,仅向MongoDB发送更新的字段:

collcetion[sindex].state = 'new state';
collcetion[hindex].state = 'new state';
collcetion.save(next);
// Mongoose sends update operation, setting only this two fields

Additionally, mongoose is using versioning to ensure that the order of documents in sub-documents array haven't changed, thus protecting you from updating wrong sub-document. 另外,猫鼬使用版本控制来确保子文档数组中的文档顺序没有更改,从而保护您免于更新错误的子文档。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM