我有一个文档,其“测试”类型为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
答案 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" }}}]
)