当前位置:  开发笔记 > 编程语言 > 正文

如何改变mongodb中的集合结构?

如何解决《如何改变mongodb中的集合结构?》经验,为你挑选了1个好方法。

我有一个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执行将解决特定问题,如果这就是你所需要的.



1> Neil Lunn..:

那么你没有回答所给出的评论,但重要的是将要解释的原因.

因此,如果你真的有"数百万份文件",你现在必须改变并迅速做到这一点,那么你就有一个明确的问题需要面对.由于没有"原子"操作可以通过"引用"现有字段中的值来处理文档以应用于更新,因此实现此目的的唯一方法是实际循环结果:

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执行将解决特定问题,如果这就是你所需要的.

推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有