Watch keynotes and sessions from MongoDB.live, our virtual developer conference.

Change type of a field in a nested array

Hi,

Each document of my collection “histo” has the following schema:

{
    "_id" : ObjectId("5ed61144376edd4a601467cd"),
    "pname" : "actual_speed",
    "values" : [ 
        {
            "timestamp" : 1580120048,
            "val" : 27716
        }, 
        {
            "timestamp" : 1580120113,
            "val" : 27730.5
        }, 
        {
            "timestamp" : 1580120138,
            "val" : 27702
        }, 
       ...
]}

I want to force the type “val” to Double. For the moment, if its value is an integer, as for “27716”, its type is int32.

I tried with:

db.getCollection("histo").find().forEach(function (e) {
  e.values.forEach(function (o) {
      o.val = parseFloat(o.val);
  });
  db.getCollection("histo").save(e);
});

But it does not work.

What is wrong ?

Thanks!

@Helene_ORTIZ

By default, in MongoDB document the type of a number is a double. In the sample document you had posted though the number 27702 is an integer, actually its type is double. This can be verified with the following query:

db.collection.aggregate([ 
  { 
      $addFields: { 
          types: { 
              $map: { input: "$values", in: { type: { $type: "$$this.val" }, val: "$$this.val" } }
          }
      }
  }
]).pretty()
1 Like

Sorrry but in my database the field containing 27702 is an integer in mongoDB.

The following update statement will update all the val field value type to double. Note this update runs in MongoDB version 4.2 or later only.

db.collection.updateMany(
{},
[
  { 
      $set: { 
          values: { 
              $map: { input: "$values", in: { $mergeObjects: [ "$$this", { val: { $toDouble: "$$this.val" } } ] } }
          }
      }
  }
] )

In case your database version is older than 4.2, then use this query:

db.collection.aggregate([ 
  { 
      $addFields: { 
          values: { 
              $map: { input: "$values", in: { $mergeObjects: [ "$$this", { val: { $toDouble: "$$this.val" } } ] } }
          }
      }
  }
] ).forEach( doc => db.collection.updateOne( { _id: doc._id }, { $set: { values: doc.values } } ) )

NOTE: The aggregation operator $toDouble used in the above queries converts a number to a double.

1 Like