如何在MongoDB Shell中将NumberDecimal转换为Double?

时间:2019-07-04 03:27:24

标签: mongodb mongodb-query decimal bigdecimal mongo-shell

我有一个文档,其“测试”类型为NumberDecimal

{ "_id" : ObjectId("5d1a202e476381c30cd995a4"),  "test" : NumberDecimal("0.1") }

如何在mongodb shell中将“测试”字段从NumberDecimal转换为Double

我尝试执行

db.collection.find({"test": {$exists: true}}).forEach(function (x) {   x.test = parseFloat(x.test);   db.collection.save(x); });

但不能解决此问题,因为它返回NaN

1 个答案:

答案 0 :(得分:3)

十进制类型不是JavaScript固有的,因此Shell中的NumberDecimal值是特殊的包装,表示存储在MongoDB中的BSON值。如果要使用parseFloat(),可以将NumberDecimal转换为JSON,以访问字符串值。例如,在您的原始代码中,该名称应为:parseFloat(x.test.toJSON()["$numberDecimal"])

但是,更好的方法是使用聚合框架来操纵十进制值,包括算术运算(MongoDB 3.4+)和类型转换(MongoDB 4.0 +)。

MongoDB 4.0+包含一个$toDouble() expression,它将数字值(十进制,整数,长整数,布尔值,日期,字符串)转换为双精度型。 MongoDB 4.0中的聚合框架不能用于更新文档(除非您要创建新集合或使用$out替换现有集合),因此您必须运行聚合查询来转换值,然后分别进行操作应用文档更新:

// Find matching documents
var docs = db.collection.aggregate([
    { $match: {
        test: { $exists: true }
    }},

    // Add a new field converting the decimal to a double
    // (alternatively, the original "test" value could also be replaced)
    { $addFields: {
        testDouble: { $toDouble: "$test" }
    }}
])

// Update with the changes (Note: this could be a bulk update for efficiency)
docs.forEach(function (doc) {
     db.collection.update({ _id: doc._id}, {$set: { testDouble: doc.testDouble }});
});

// Check the results
> db.collection.find().limit(1)
{
    "_id" : ObjectId("5d1a202e476381c30cd995a4"),
    "test" : NumberDecimal("0.1"),
    "testDouble" : 0.1
}

MongoDB 4.2(当前在RC中)增加了对使用某些aggregation stages for updates的支持,因此在4.2中,上述更新可以更简洁地表示为:

db.collection.updateMany(
    { test: { $exists: true }},
    [ { $addFields: { testDouble: { $toDouble: "$test" }}}]
)