如何在更新文档时实现类似于db.collection.find().limit(10)的东西?现在我使用的是一些非常糟糕的东西,比如用db.collection.find().limit()获取文档,然后更新它们。一般来说,我想返回给定数量的记录,并在每个记录中更改一个字段。谢谢。
db.collection.find().limit(10)
db.collection.find().limit()
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} );
bz4sfanl2#
使用forEach单独更新每个文档速度较慢。您可以使用
forEach
ids = db.collection.find(<condition>).limit(<limit>).map( function(doc) { return doc._id; } ); db.collection.updateMany({_id: {$in: ids}}, <update>})
ddrv8njm3#
迭代所有对象然后单独更新它们的解决方案非常慢。使用$in检索所有文件然后同时更新会更高效。
$in
ids = People.where(firstname: 'Pablo').limit(10000).only(:_id).to_a.map(&:id) People.in(_id: ids).update_all(lastname: 'Cantero')
该查询是使用Mongoid编写的,但也可以很容易地用MongoShell重写。
2cmtqfgy4#
不幸的是,你的变通方案是唯一的方法AFAIK。有一个布尔标记multi,它将更新所有匹配(当true)或更新第一个匹配(当false)。
multi
true
false
46scxncf5#
正如答案所述,仍然无法将要更新(或删除)的文档数限制为大于1的值。解决方法如下:
db.collection.find(<condition>).limit(<limit>).forEach(function(doc){db.collection.update({_id:doc._id},{<your update>})})
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>}) }
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"} })
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。
8条答案
按热度按时间iq0todco1#
您可以使用:
(forEach代码的学分:MongoDB:使用同一文档中的数据更新文档)
这样做只会改变你指定的条目数,所以如果你想添加一个名为"newField"的值为1的字段到"collection"中的一半条目中,你可以把
如果你想让另一半也有"newField",但是值为2,你可以在newField不存在的条件下进行更新:
bz4sfanl2#
使用
forEach
单独更新每个文档速度较慢。您可以使用ddrv8njm3#
迭代所有对象然后单独更新它们的解决方案非常慢。
使用
$in
检索所有文件然后同时更新会更高效。该查询是使用Mongoid编写的,但也可以很容易地用MongoShell重写。
2cmtqfgy4#
不幸的是,你的变通方案是唯一的方法AFAIK。有一个布尔标记
multi
,它将更新所有匹配(当true
)或更新第一个匹配(当false
)。46scxncf5#
正如答案所述,仍然无法将要更新(或删除)的文档数限制为大于1的值。解决方法如下:
p3rjfoxz6#
如果你的id是一个序列号而不是一个ObjectId,你可以在for循环中完成这个操作:
pobjuy327#
ntjbwcob8#
我最近也想做这样的事情,我认为查询一长串的_id来更新一个$in可能太慢了,所以我尝试使用聚合+合并
但请随时评论,如果这是更好或更坏的批量更新与$in。