只要您可以创建数据副本,这里就可以使用聚合框架作为替代方案。如果您希望使用其他运算符,您还可以选择对数据执行更多操作,但您唯一需要的是$project。它在空间方面有点浪费,但可能更快,更适合某些用途。为了说明,我将首先将一些示例数据插入到foo 集合中:
db.foo.insert({ 'lat': 1, 'lon': 2, someotherdata : [1, 2, 3] })
db.foo.insert({ 'lat': 4, 'lon': 1, someotherdata : [4, 5, 6] })
现在,我们只需使用$project 重新处理lat 和lon 字段,然后将它们发送到newfoo 集合:
db.foo.aggregate([
{$project : {_id : "$_id", "coords.lat" : "$lat", "coords.lon" : "$lon", "someotherdata" : "$someotherdata" }},
{ $out : "newfoo" }
])
然后检查 newfoo 以获取我们更改的数据:
db.newfoo.find()
{ "_id" : ObjectId("544548a71b5cf91c4893eb9a"), "someotherdata" : [ 1, 2, 3 ], "coords" : { "lat" : 1, "lon" : 2 } }
{ "_id" : ObjectId("544548a81b5cf91c4893eb9b"), "someotherdata" : [ 4, 5, 6 ], "coords" : { "lat" : 4, "lon" : 1 } }
一旦您对新数据感到满意,您就可以使用renameCollection() 命令删除旧数据并使用旧名称下的新数据:
> db.newfoo.renameCollection("foo", true)
{ "ok" : 1 }
> db.foo.find()
{ "_id" : ObjectId("544548a71b5cf91c4893eb9a"), "someotherdata" : [ 1, 2, 3 ], "coords" : { "lat" : 1, "lon" : 2 } }
{ "_id" : ObjectId("544548a81b5cf91c4893eb9b"), "someotherdata" : [ 4, 5, 6 ], "coords" : { "lat" : 4, "lon" : 1 } }
最后一点 - 在完成SERVER-7944 之前,您无法按照this answer 中的建议通过提示_id 索引来执行相当于快照的操作,因此如果有活动,您最终可能会多次点击文档其他地方使它移动。由于您在此示例中插入了 _id 字段,因此任何此类事件都会导致唯一密钥冲突,因此您不会最终得到欺骗,但您可能有一个“旧”版本的文档。与往常一样,在删除数据之前彻底检查您的数据,并最好进行备份。