Mongodb 更新mongo文档的性能问题

Mongodb 更新mongo文档的性能问题,mongodb,Mongodb,我有一个mongo集合,有大约4M条记录,该集合的两个文档字段是日期作为字符串,我需要将它们更改为ISODate,所以使用这个小脚本来实现这一点: db.vendors.find().forEach(function(el){ el.lastEdited = new Date(el.lastEdited); el.creationDate = new Date(el.creationDate) db.vendors.save(el) }) 但是这需要很长的时间…我在这些

我有一个mongo集合,有大约4M条记录,该集合的两个文档字段是日期作为字符串,我需要将它们更改为ISODate,所以使用这个小脚本来实现这一点:

db.vendors.find().forEach(function(el){
    el.lastEdited = new Date(el.lastEdited);
    el.creationDate = new Date(el.creationDate)
    db.vendors.save(el)
})

但是这需要很长的时间…我在这些字段中添加了索引,难道我不能用其他方式完成这项工作,这将是合理的时间吗?

目前,您需要对整个集合执行
查找
,这可能需要一段时间,对于每个
保存
调用,它必须执行从客户端(shell)到服务器的网络往返。
编辑:删除了使用$match并分批执行此操作的建议,因为
$out
实际上会在每次运行时替换@Stennie的注释中所述的集合

(不用说,首先在测试环境中在示例数据集中测试它。我还没有测试new Date()的行为,因为我不知道您的数据格式)


目前,您对整个集合执行
查找
,这可能需要一些时间,而且对于每个
保存
调用,它必须执行从客户端(shell)到服务器的网络往返。
编辑:删除了使用$match并分批执行此操作的建议,因为
$out
实际上会在每次运行时替换@Stennie的注释中所述的集合

(不用说,首先在测试环境中在示例数据集中测试它。我还没有测试new Date()的行为,因为我不知道您的数据格式)


索引无关紧要——您正在遍历所有400万个文档,而根本不进行过滤。如果有什么不同的话,索引可能会增加时间,如果您对这两个属性进行了索引(因为索引也必须写入)。不要更新数据库。当使用它作为date@DavidMakogon感谢您的回复和索引解释。因此,基本上没有更快的方法,只需等待1-2小时即可完成?索引无关紧要-您正在迭代所有400万个文档,而根本不进行过滤。如果有什么不同的话,索引可能会增加时间,如果您对这两个属性进行了索引(因为索引也必须写入)。不要更新数据库。当使用它作为date@DavidMakogon感谢您的回复和索引解释。因此,基本上没有更快的方法,只需等待1-2个小时就可以完成?允许您在聚合中添加或替换字段,而无需指定所有现有字段。请注意,使用
$out
操作符将源集合指定为目标,因此建议在没有
$match
阶段的情况下执行此操作(除非缺少不匹配的文档是可以的)。@Stennie,感谢您指出这一点。我们也有一个类似于OP(字符串到int32)的要求,最后我们用OP在帖子中的save做了forEach。幸运的是,我们的收藏量并没有那么大(约20万份文档),只花了20分钟就完成了。有没有其他实用程序可以有效地执行此操作?我不知道有任何具体的实用程序可以执行此操作,但我认为为shell(或您最喜欢的驱动程序)编写脚本是很简单的。字段类型之间的迁移要求很可能是定制的。如果只更新几个字段,我认为一种更有效的方法是使用仅限于更新所需字段的投影来迭代集合。我将把离散字段更新(使用
$set
$unset
)作为无序批量写入操作排队,而不是使用
save()
通过线路发送整个文档。自动将操作分组为批,无序的大容量写入操作比有序的快。驱动程序会自动将批量写入操作分组到批中,但如果您需要更多控制(例如,改变批大小或大小),您可以自己创建批。允许您在聚合中添加或替换字段,而无需指定所有现有字段。请注意,使用
$out
操作符将源集合指定为目标,因此建议在没有
$match
阶段的情况下执行此操作(除非缺少不匹配的文档是可以的)。@Stennie,感谢您指出这一点。我们也有一个类似于OP(字符串到int32)的要求,最后我们用OP在帖子中的save做了forEach。幸运的是,我们的收藏量并没有那么大(约20万份文档),只花了20分钟就完成了。有没有其他实用程序可以有效地执行此操作?我不知道有任何具体的实用程序可以执行此操作,但我认为为shell(或您最喜欢的驱动程序)编写脚本是很简单的。字段类型之间的迁移要求很可能是定制的。如果只更新几个字段,我认为一种更有效的方法是使用仅限于更新所需字段的投影来迭代集合。我将把离散字段更新(使用
$set
$unset
)作为无序批量写入操作排队,而不是使用
save()
通过线路发送整个文档。自动将操作分组为批,无序的大容量写入操作比有序的快。驱动程序会自动将批量写入操作分组到批中,但是如果您想要更多的控制(例如,改变批大小或大小),您可以自己创建批。
db.vendors.aggregate([

         {
            $project: {
               _id: 1,
               lastEdited: { $add : [new Date('$lastEdited')]},
               creationDate: { $add : [new Date('$creationDate')]},
               field1: 1,
               field2: 1,
               //.. (important to repeat all necessary fields)
            },
         },
         {
            $out: 'vendors',
         },
      ]);