MongoDb - 将类型从Int更改为Double

时间:2015-07-07 09:42:16

标签: mongodb casting

我们有一个如下所示的集合:

{
    "_id" : "10571:6",
    "v" : 261355,
    "ts" : 4.88387e+008
}

现在,有些" v"是整数,有些是双打。我想将它们全部改为双打。

我尝试了一些事情,但没有任何作用(v是此记录的int32,我想将其更改为double):

db.getCollection('VehicleLastValues')
.find
(

    {_id : "10572:6"}
)
.forEach
(
function (x)
{
    temp = x.v * 1.0;
    db.getCollection('VehicleLastValues').save(x);
}}

我尝试的事情:

x.v = x.v * 1.1 / 1.1;
x.v = parseFloat (new String(x.v));

但我无法将其保存为双人......

1 个答案:

答案 0 :(得分:9)

默认情况下,所有“数字”在MongoDB中都存储为“double”,除非一般是过度施放。

采取以下样本:

db.sample.insert({ "a": 1 })
db.sample.insert({ "a": NumberLong(1) })
db.sample.insert({ "a": NumberInt(1) })
db.sample.insert({ "a": 1.223 })

这会产生这样的集合:

{ "_id" : ObjectId("559bb1b4a23c8a3da73e0f76"), "a" : 1 }
{ "_id" : ObjectId("559bb1bba23c8a3da73e0f77"), "a" : NumberLong(1) }
{ "_id" : ObjectId("559bb29aa23c8a3da73e0f79"), "a" : 1 }
{ "_id" : ObjectId("559bb30fa23c8a3da73e0f7a"), "a" : 1.223 }

尽管构造函数不同,但请注意其中的几个数据点看起来大致相同。 MongoDB shell本身并不总是明确区分它们,但有一种方法可以告诉你。

当然有$type查询运算符,它允许选择BSON类型。

因此使用类型1进行测试 - 这是“双重”:

> db.sample.find({ "a": { "$type": 1 } })
{ "_id" : ObjectId("559bb1b4a23c8a3da73e0f76"), "a" : 1 }
{ "_id" : ObjectId("559bb30fa23c8a3da73e0f7a"), "a" : 1.223 }

您会看到第一个插入和最后一个插入都被选中,但当然不是其他两个插入。

现在测试BSON Type 16 - 这是一个32位整数

> db.sample.find({ "a": { "$type": 16 } })
{ "_id" : ObjectId("559bb29aa23c8a3da73e0f79"), "a" : 1 }

这是在shell中使用NumberInt()函数的“第三个”插入。因此,驱动程序中的函数和其他序列化可以设置此特定的BSON类型。

对于BSON类型18 - 这是64位整数

> db.sample.find({ "a": { "$type": 18 } })
{ "_id" : ObjectId("559bb1bba23c8a3da73e0f77"), "a" : NumberLong(1) }

通过NumberLong()构建的“第二个”插入。

如果你想“清除”那些“不是双重”的东西,那么你会这样做:

db.sample.find({ "$or": [{ "a": { "$type": 16 } },{ "a": { "$type": 18 } }]})

除了“double”本身之外,其他唯一有效的数字类型。

所以要在你的收藏中“转换”这些,你可以像这样“批量”处理:

var bulk = db.sample.initializeUnorderedBulkOp(),
    count = 0;
db.sample.find({ 
    "$or": [
        { "a": { "$type": 16 } },
        { "a": { "$type": 18 } }
    ]
}).forEach(function(doc) {
    bulk.find({ "_id": doc._id })
        .updateOne({ 
            "$set": { "b": doc.a.valueOf() } ,
            "$unset": { "a": 1 } 
        });
    bulk.find({ "_id": doc._id })
        .updateOne({ "$rename": { "b": "a" } });
    count++;
    if ( count % 1000 == 0 ) {
        bulk.execute()
        bulk = db.sample.initializeUnOrderedBulkOp();
    }
})
if ( count % 1000 != 0 ) bulk.execute();

通过“批量”三个步骤执行的操作:

  1. 将值重新转换为新字段为“double”
  2. 删除不需要类型的旧字段
  3. 将新字段重命名为旧字段名称
  4. 这是必要,因为BSON类型信息在创建后对字段元素是“粘性的”。因此,为了“重新投射”,您需要完全删除包含原始字段分配的旧数据。

    这应该解释如何在文档中“检测”并“重新投射”不需要的类型。