suj*_*yur 3 php collections alter-table mongodb
我有一个mongodb集合
{
"_id" : 57,
"value" : {
"user" : [
{
"fk_status_id" : "0",
"firstname" : "Ajith",
"lastname" : "S",
"city" : "known",
"State" :"kerala",
"location" : {
"lat" : 34.123456,
"lon" : -95.123456
},
}
],
}}
Run Code Online (Sandbox Code Playgroud)
拥有数百万份文件
我想像这样改变表结构
{
"_id" : 58,
"user" : [
{
"fk_status_id" : "0",
"firstname" : "Ajith",
"lastname" : "S",
"city" : "known",
"State" :"kerala",
"location" : {
"lat" : 34.123456,
"lon" : -95.123456
},
}
]}
Run Code Online (Sandbox Code Playgroud)
我的意思是,我想从这个结构中省略'value {}'.
那么你没有回答所给出的评论,但重要的是将要解释的原因.
因此,如果你真的有"数百万份文件",你现在必须改变并迅速做到这一点,那么你就有一个明确的问题需要面对.由于没有"原子"操作可以通过"引用"现有字段中的值来处理文档以应用于更新,因此实现此目的的唯一方法是实际循环结果:
db.collection.find().forEach(function(doc) {
var user = doc.value.user;
delete doc.value;
db.collection.update(
{ "_id": doc._id },
{ "$set": { "user": user } }
);
})
Run Code Online (Sandbox Code Playgroud)
所以这是基本过程,对于大型数据集来说它有点可怕.
但是有一种方法可以做到"一次性"转换,虽然这不是一个非常好的方法,它被称为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 } }
);
});
});
Run Code Online (Sandbox Code Playgroud)
当然,正如所建议的,还有其他方法来解决这个问题.
mapReduce可以在没有锁定问题的情况下执行此操作,但输出仍然需要大量重新整形以及集合重命名和替换.
实际上在服务器上运行(或最接近网络术语),这可能是最好的选择.通过这种方式,您可以安全地编码并避免扩展锁定问题.
但是,如果你真的"陷入困境",那么服务器上的JavaScript执行将解决特定问题,如果这就是你所需要的.
| 归档时间: |
|
| 查看次数: |
2299 次 |
| 最近记录: |