php - 如何更改 mongodb 中的集合结构?

标签 php mongodb collections alter-table

我有一个像这样的 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
            },
     }

    ]}

我的意思是,我想从这个结构中省略“值{}”。

  • 数据应该在“值”之外。 请解决我的问题。

最佳答案

好吧,您没有回答给出的评论,但由于将要解释的原因,它很重要。

因此,如果您现在确实有“数以百万计的文档”必须更改并快速执行此操作,那么您将面临一个明显的问题。由于没有“原子”操作可以通过“引用”现有字段中的值来对文档进行操作以应用于更新,因此唯一的方法是实际循环结果:

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):

WARNING

  • By default, db.eval() takes a global write lock before evaluating the JavaScript function. As a result, db.eval() blocks all other read and write operations to the database while the db.eval() operation runs. Set nolock to true on the eval command to prevent the eval command from taking the global write lock before evaluating the JavaScript. nolock does not impact whether operations within the JavaScript code itself takes a write lock.

  • Do not use db.eval() for long running operations as db.eval() blocks all other operations. Consider using other server side code execution options.

  • You can not use db.eval() with sharded data. In general, you should avoid using db.eval() in sharded cluster; nevertheless, it is possible to use db.eval() with non-sharded collections and databases stored in a sharded cluster.

  • With authentication enabled, db.eval() will fail during the operation if you do not have the permission to perform a specified task.

Changed in version 2.4: You must have full admin access to run.

有了这个,如果这确实符合您的情况,那么我们就不必像鸵鸟一样(并将我们的头埋在沙子“神话”中)并实际做一些可以在服务器上运行的东西来做到这一点:

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 可以在没有锁定问题的情况下做到这一点,但输出仍然需要大量的 reshape 以及集合重命名和替换。

  • 实际在服务器(或网络术语中最接近的服务器)上运行,这可能是最好的选择。通过这种方式,您可以安全地编码并避免扩展锁定问题。

但如果您确实“陷入困境”,服务器上的 JavaScript 执行将解决该特定问题(如果您需要的话)。

关于php - 如何更改 mongodb 中的集合结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23124679/

相关文章:

php - 如何在 WordPress 中将图像添加到自定义主题本身?

java - MongoJack 和 updateById 的使用

mongodb - 无法使用来自 c# 的 x509 证书身份验证连接到 MongoDB 服务器

java - Couchbase : List available Buckets, 范围和集合可在具有 Java SDK 3 的集群中使用

java - 为什么 Collection<E>#toArray() 不返回 E[]?

php - MySQL 开销 - 如何调整服务器以加速不良查询

php - 我有一个连接到 phpmyadmin 的 laravel 网站,但现在我想将 android 应用程序连接到同一个数据库

arrays - Mongodb 如何删除/清除另一个数组中的数组

php 连接到 mysql 不起作用(raspberry pi 3/apache2)

javascript - 在 Meteor 应用程序上,根据 Mongo 中的字段值向从 Mongo 接收的数据添加类