如何在mongodb中限制更新文档的数量

ktca8awb  于 2022-12-26  发布在  Go
关注(0)|答案(8)|浏览(278)

如何在更新文档时实现类似于db.collection.find().limit(10)的东西?
现在我使用的是一些非常糟糕的东西,比如用db.collection.find().limit()获取文档,然后更新它们。
一般来说,我想返回给定数量的记录,并在每个记录中更改一个字段。
谢谢。

iq0todco

iq0todco1#

您可以使用:

db.collection.find().limit(NUMBER_OF_ITEMS_YOU_WANT_TO_UPDATE).forEach(
    function (e) {
        e.fieldToChange = "blah";
        ....
        db.collection.save(e);
    }
);

(forEach代码的学分:MongoDB:使用同一文档中的数据更新文档)
这样做只会改变你指定的条目数,所以如果你想添加一个名为"newField"的值为1的字段到"collection"中的一半条目中,你可以把

db.collection.find().limit(db.collection.count() / 2).forEach(
    function (e) {
        e.newField = 1;
        db.collection.save(e);
    }
);

如果你想让另一半也有"newField",但是值为2,你可以在newField不存在的条件下进行更新:

db.collection.update( { newField : { $exists : false } }, { $set : { newField : 2 } }, {multi : true} );
bz4sfanl

bz4sfanl2#

使用forEach单独更新每个文档速度较慢。您可以使用

ids = db.collection.find(<condition>).limit(<limit>).map(
    function(doc) {
        return doc._id;
    }
);
db.collection.updateMany({_id: {$in: ids}}, <update>})
ddrv8njm

ddrv8njm3#

迭代所有对象然后单独更新它们的解决方案非常慢。
使用$in检索所有文件然后同时更新会更高效。

ids = People.where(firstname: 'Pablo').limit(10000).only(:_id).to_a.map(&:id)
People.in(_id: ids).update_all(lastname: 'Cantero')

该查询是使用Mongoid编写的,但也可以很容易地用MongoShell重写。

2cmtqfgy

2cmtqfgy4#

不幸的是,你的变通方案是唯一的方法AFAIK。有一个布尔标记multi,它将更新所有匹配(当true)或更新第一个匹配(当false)。

46scxncf

46scxncf5#

正如答案所述,仍然无法将要更新(或删除)的文档数限制为大于1的值。解决方法如下:

db.collection.find(<condition>).limit(<limit>).forEach(function(doc){db.collection.update({_id:doc._id},{<your update>})})
p3rjfoxz

p3rjfoxz6#

如果你的id是一个序列号而不是一个ObjectId,你可以在for循环中完成这个操作:

let batchSize= 10;
for (let i = 0; i <= 1000000; i += batchSize) { 
  db.collection.update({$and :[{"_id": {$lte: i+batchSize}}, {"_id": {$gt: i}}]}),{<your update>})
}
pobjuy32

pobjuy327#

let fetchStandby = await db.model.distinct("key",{});
    fetchStandby = fetchStandby.slice(0, no_of_docs_to_be_updated)
    let fetch = await db.model.updateMany({
        key: { $in: fetchStandby }
    }, {
        $set:{"qc.status": "pending"}
    })
ntjbwcob

ntjbwcob8#

我最近也想做这样的事情,我认为查询一长串的_id来更新一个$in可能太慢了,所以我尝试使用聚合+合并

while (true) {
    const record = db.records.findOne({ isArchived: false }, {_id: 1})
    if (!record) {
        print("No more records")
        break
    }
    
    db.records.aggregate([
        { $match: { isArchived: false } },
        { $limit: 100 },
        { 
            $project: { 
                _id: 1, 
                isArchived: { 
                    $literal: true 
                }, 
                updatedAt: {
                    $literal: new Date()      
                } 
            } 
        },
        { 
            $merge: {
                into: "records",
                on: "_id",
                whenMatched: "merge"
            }
        }
    ])   
    print("Done update")
}

但请随时评论,如果这是更好或更坏的批量更新与$in。

相关问题