我有一个mongodb集合
{ "_id" : 57, "value" : { "user" : [ { "fk_status_id" : "0", "firstname" : "Ajith", "lastname" : "S", "city" : "known", "State" :"kerala", "location" : { "lat" : 34.123456, "lon" : -95.123456 }, } ], }}
拥有数百万份文件
我想像这样改变表结构
{ "_id" : 58, "user" : [ { "fk_status_id" : "0", "firstname" : "Ajith", "lastname" : "S", "city" : "known", "State" :"kerala", "location" : { "lat" : 34.123456, "lon" : -95.123456 }, } ]}
我的意思是,我想从这个结构中省略'value {}'.
数据应该超出'价值'.请解决我的问题.
Neil Lunn.. 6
那么你没有回答所给出的评论,但重要的是将要解释的原因.
因此,如果你真的有"数百万份文件",你现在必须改变并迅速做到这一点,那么你就有一个明确的问题需要面对.由于没有"原子"操作可以通过"引用"现有字段中的值来处理文档以应用于更新,因此实现此目的的唯一方法是实际循环结果:
db.collection.find().forEach(function(doc) { var user = doc.value.user; delete doc.value; db.collection.update( { "_id": doc._id }, { "$set": { "user": user } } ); })
所以这是基本过程,对于大型数据集来说它有点可怕.
但是有一种方法可以做到"一次性"转换,虽然这不是一个非常好的方法,它被称为db.eval()
方法.但请注意文档(手册页中的Big Rip):
警告
默认情况下,db.eval()在评估JavaScript函数之前采用全局写锁定.因此,当db.eval()操作运行时,db.eval()会阻止对数据库的所有其他读写操作.在eval命令中将nolock设置为true,以防止eval命令在评估JavaScript之前采用全局写锁定.nolock不影响JavaScript代码本身内的操作是否采用写锁定.
不要将db.eval()用于长时间运行的操作,因为db.eval()会阻止所有其他操作.考虑使用其他服务器端代码执行选项.
不能使用db.eval()与分片数据.通常,应避免在分片集群中使用db.eval(); 尽管如此,可以将db.eval()与非分片集合和数据库一起存储在分片集群中.
启用身份验证后,如果您没有执行指定任务的权限,db.eval()将在操作期间失败.
版本2.4中已更改:您必须具有完全管理员权限才能运行.
如果这样做完全符合你的环境,那么我们就不需要鸵鸟了(并把我们的头埋在沙子里"神话")并且实际上做一些可以在服务器上运行的东西:
db.eval(function() { db.collection.find().forEach(function(doc) { var user = doc.value.user; delete doc.value; db.collection.update( { "_id": doc._id }, { "$set": { "user": user } } ); }); });
当然,正如所建议的,还有其他方法来解决这个问题.
mapReduce可以在没有锁定问题的情况下执行此操作,但输出仍然需要大量重新整形以及集合重命名和替换.
实际上在服务器上运行(或最接近网络术语),这可能是最好的选择.通过这种方式,您可以安全地编码并避免扩展锁定问题.
但是,如果你真的"陷入困境",那么服务器上的JavaScript执行将解决特定问题,如果这就是你所需要的.
那么你没有回答所给出的评论,但重要的是将要解释的原因.
因此,如果你真的有"数百万份文件",你现在必须改变并迅速做到这一点,那么你就有一个明确的问题需要面对.由于没有"原子"操作可以通过"引用"现有字段中的值来处理文档以应用于更新,因此实现此目的的唯一方法是实际循环结果:
db.collection.find().forEach(function(doc) { var user = doc.value.user; delete doc.value; db.collection.update( { "_id": doc._id }, { "$set": { "user": user } } ); })
所以这是基本过程,对于大型数据集来说它有点可怕.
但是有一种方法可以做到"一次性"转换,虽然这不是一个非常好的方法,它被称为db.eval()
方法.但请注意文档(手册页中的Big Rip):
警告
默认情况下,db.eval()在评估JavaScript函数之前采用全局写锁定.因此,当db.eval()操作运行时,db.eval()会阻止对数据库的所有其他读写操作.在eval命令中将nolock设置为true,以防止eval命令在评估JavaScript之前采用全局写锁定.nolock不影响JavaScript代码本身内的操作是否采用写锁定.
不要将db.eval()用于长时间运行的操作,因为db.eval()会阻止所有其他操作.考虑使用其他服务器端代码执行选项.
不能使用db.eval()与分片数据.通常,应避免在分片集群中使用db.eval(); 尽管如此,可以将db.eval()与非分片集合和数据库一起存储在分片集群中.
启用身份验证后,如果您没有执行指定任务的权限,db.eval()将在操作期间失败.
版本2.4中已更改:您必须具有完全管理员权限才能运行.
如果这样做完全符合你的环境,那么我们就不需要鸵鸟了(并把我们的头埋在沙子里"神话")并且实际上做一些可以在服务器上运行的东西:
db.eval(function() { db.collection.find().forEach(function(doc) { var user = doc.value.user; delete doc.value; db.collection.update( { "_id": doc._id }, { "$set": { "user": user } } ); }); });
当然,正如所建议的,还有其他方法来解决这个问题.
mapReduce可以在没有锁定问题的情况下执行此操作,但输出仍然需要大量重新整形以及集合重命名和替换.
实际上在服务器上运行(或最接近网络术语),这可能是最好的选择.通过这种方式,您可以安全地编码并避免扩展锁定问题.
但是,如果你真的"陷入困境",那么服务器上的JavaScript执行将解决特定问题,如果这就是你所需要的.