【问题标题】:How to change datatype of nested field in Mongo document?如何更改 Mongo 文档中嵌套字段的数据类型?
【发布时间】:2014-12-16 06:35:53
【问题描述】:

我的 Mongo 结构如下,

"topProcesses" : [
        {
            "cpuUtilizationPercent" : "0.0",
            "processId" : "1",
            "memoryUtilizationPercent" : "0.1",
            "command" : "init",
            "user" : "root"
        },
        {
            "cpuUtilizationPercent" : "0.0",
            "processId" : "2",
            "memoryUtilizationPercent" : "0.0",
            "command" : "kthreadd",
            "user" : "root"
        },
        {
            "cpuUtilizationPercent" : "0.0",
            "processId" : "3",
            "memoryUtilizationPercent" : "0.0",
            "command" : "ksoftirqd/0",
            "user" : "root"
        },
        {
            "cpuUtilizationPercent" : "0.0",
            "processId" : "5",
            "memoryUtilizationPercent" : "0.0",
            "command" : "kworker/0:+",
            "user" : "root"
        },
        {
            "cpuUtilizationPercent" : "0.0",
            "processId" : "6",
            "memoryUtilizationPercent" : "0.0",
            "command" : "kworker/u3+",
            "user" : "root"
        },
        {
            "cpuUtilizationPercent" : "0.0",
            "processId" : "8",
            "memoryUtilizationPercent" : "0.0",
            "command" : "rcu_sched",
            "user" : "root"
        } 
    ]

现在在上述文档中topProcesses.cpuUtilizationPercent 是字符串,我想将topProcesses.cpuUtilizationPercent 数据类型更改为Float。为此,我在下面尝试过,但没有成功

db.collectionName.find({
   "topProcesses":{"$exists":true}}).forEach(function(data){
    for(var ii=0;ii<data.topProcesses.length;ii++){
   db.collectionName.update({_id: data._id},{$set:{"topProcesses.$.cpuUtilizationPercent":parseFloat(data.topProcesses[ii].cpuUtilizationPercent)}},false,true);
  }
})

任何人都可以帮助如何将字符串更改为在嵌套的 Mongo 文档中浮动

【问题讨论】:

    标签: mongodb mongodb-query


    【解决方案1】:

    您以正确的方式执行此操作,但您没有在 .update() 的查询部分中包含要匹配的数组元素:

    db.collectionName.find({
       "topProcesses":{"$exists":true}}).forEach(function(data){
        for(var ii=0;ii<data.topProcesses.length;ii++) {
          db.collectionName.update(
             { 
                 "_id": data._id, 
                 "topProcesses.processId": data.topProcesses[ii].processId // corrected
             },
             {
                 "$set": {
                   "topProcesses.$.cpuUtilizationPercent":
                       parseFloat(data.topProcesses[ii].cpuUtilizationPercent)
                 }
             }
          );
      }
    })
    

    因此,您需要匹配数组中的某些内容才能使 positional $ 运算符产生任何效果。

    您也可以只使用符号中的“索引”值,因为无论如何您都是在循环中生成它:

    db.collectionName.find({
       "topProcesses":{"$exists":true}}).forEach(function(data){
        for(var ii=0;ii<data.topProcesses.length;ii++) {
    
          var updoc =  { 
              "$set": {}
          };
    
          var myKey = "topProcesses." + ii + ".cpuUtilizationPercent";
          updoc["$set"][myKey] = parseFloat(data.topProcesses[ii].cpuUtilizationPercent);
    
          db.collectionName.update(
             { 
                 "_id": data._id
             },
             updoc
          );
      }
    })
    

    仅使用匹配索引,在没有数组元素唯一标识符的情况下很方便。

    另请注意,由于处理现有文档的方式的性质,此处不应使用“upsert”或“multi”选项。


    正如对此的“附注”一样,考虑 2.6 及更高版本中 MongoDB 的批量操作 API 也是值得的。使用这些 API 方法,您可以显着减少客户端应用程序和数据库之间的网络流量。这里明显的改进在于整体速度:

    var bulk = db.collectionName.initializeOrderedBulkOp();
    var counter = 0;
    
    db.collectionName.find({
       "topProcesses":{"$exists":true}}
    ).forEach(function(data){
        for(var ii=0;ii<data.topProcesses.length;ii++) {
    
          var updoc =  { 
              "$set": {}
          };
    
          var myKey = "topProcesses." + ii + ".cpuUtilizationPercent";
          updoc["$set"][myKey] = parseFloat(data.topProcesses[ii].cpuUtilizationPercent);
    
          // queue the update
          bulk.find({ "_id": data._id }).update(updoc);
          counter++;
    
          // Drain and re-initialize every 1000 update statements
          if ( counter % 1000 == 0 ) {
              bulk.execute();
              bulk = db.collectionName.initializeOrderedBulkOp();
          }
      }
    })
    
    // Add the rest in the queue
    if ( counter % 1000 != 0 )
        bulk.execute();
    

    这基本上将发送到服务器的操作语句数量减少到每 1000 个排队操作仅发送一次。您可以使用该数字以及事物的分组方式,但它会以相对安全的方式显着提高速度。

    【讨论】:

      【解决方案2】:

      您可以使用以下查询将 topProcesses.cpuUtilizationPercent 的数据类型从字符串更新为浮点数

      db.db.find({"topProcesses.cpuUtilizationPercent" : {$exists : true}}).
      forEach( function(obj)
      { obj.topProcesses.cpuUtilizationPercent = new ISODate(obj.topProcesses.cpuUtilizationPercent);
      db.db.save(obj); } );
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-20
        • 2018-02-01
        • 2020-05-25
        相关资源
        最近更新 更多