doudichu1358 2014-04-17 04:35
浏览 929
已采纳

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

I have a mongodb collection like

{
"_id" : 57,
"value" : {
    "user" : [ 
     {
            "fk_status_id"  : "0",
            "firstname"     : "Ajith",
            "lastname"      : "S",
            "city"          : "known",
            "State"         :"kerala",          
            "location" : {
                "lat" : 34.123456,
                "lon" : -95.123456
            },
     }

    ],
}}

with millions of documents

I want to alter the table structure like this

{
"_id" : 58,
    "user" : [ 
     {
            "fk_status_id"  : "0",
            "firstname"     : "Ajith",
            "lastname"      : "S",
            "city"          : "known",
            "State"         :"kerala",          
            "location" : {
                "lat" : 34.123456,
                "lon" : -95.123456
            },
     }

    ]}

I mean ,I want to omit the 'value{}' from this structure.

  • The data should come outside 'values'. Please resolve my problem.
  • 写回答

1条回答 默认 最新

  • doumu4916 2014-04-17 09:55
    关注

    Well you didn't answer the comment that was given, but it is important for the reasons that will be explained.

    So If you truly have "millions of documents" that you now have to alter and do this quickly then you have a clear problem to face. Since there is no "atomic" operation that can act on a document by "referencing" a value in an existing field to apply to an update the only way to do this is by actually looping the results:

    db.collection.find().forEach(function(doc) {
        var user = doc.value.user;
    
        delete doc.value;
    
       db.collection.update(
           { "_id": doc._id },
           { "$set": { "user": user } }
       );
    
    })
    

    So that is the basic process and it is kind of horrible for large data sets.

    But there is a way to do this for a "one off" transformation, though it is not a really nice way to do this, and it is called the db.eval() method. But please note the documentation (Big Rip from the manual page):

    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.

    With that out of the way and if this actually meets your circumstance, then we need not be ostriches ( and bury our heads in the sand "myth" ) and actually do something that can run on the server to do this:

    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 } }
            );
    
        });
    
    });
    

    Of course as suggested there are other ways to approach this.

    • mapReduce can sort of do this without the locking issues, but the output is still going to need a lot of reshaping and also collection renaming and replacement.

    • Run actually on the sever ( or closest in network terms ) which is probably really the best option. In this way you can code safely and avoid extended locking issues.

    But if you are really "in a jam" as it were, the JavaScript execution on the server will fix that specific problem if that is what you need.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!