I have a collection that has some fields that should be integers. Due to a software bug, some of these values are strings. I need to convert them. Here is an example document:

var coll = db.getCollection('info');
coll.find({ id: "985517" });

Result:

{
    "_id" : "41cbb4e48284c0612a1c4b3ee5e3e2720c01197a",
    "id" : "985517",
    "title" : "009_1a.jpg",
    "ext" : ".jpg",
    "content_type" : "image/jpeg; charset=utf-8",
    "sha1" : "41cbb4e48284c0612a1c4b3ee5e3e2720c01197a",
    "has_thumb" : true,
    "size" : 2917,  
    "width_px" : "70",
    "height_px" : "69"
}

I try to convert width_px and height_px values into integers. My first naive try:

var coll = db.getCollection('info');
var bulk = coll.initializeOrderedBulkOp();
var counter = 0;
coll.find({ width_px: { $type: "string" }, id: "985516" }).limit(100).forEach(function(data) {
    var updoc = {
        "$set": {}
    };
    updoc["$set"]["width_px"] = parseInt(data.width_px);
    // 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 = coll.initializeOrderedBulkOp();
    }
    })
    // Add the rest in the queue
if (counter % 1000 != 0) bulk.execute();

The result is dissapointing:

{
    "_id" : "41cbb4e48284c0612a1c4b3ee5e3e2720c01197a",
    "id" : "985517",
    "title" : "009_1a.jpg",
    "ext" : ".jpg",
    "content_type" : "image/jpeg; charset=utf-8",
    "sha1" : "41cbb4e48284c0612a1c4b3ee5e3e2720c01197a",
    "has_thumb" : true,
    "size" : 2917,  
    "width_px" : 70.0,
    "height_px" : "69"
}

So it was updated to double, instead of int32. I understand that in JavaScript, there is no separate double and integer type, just "number". But I need to update 100 000 documents and I want to do this efficiently.

But how?

有帮助吗?

解决方案 2

The solution is to use NumberInt instead of parseInt.

var coll = db.getCollection('info');
var bulk = coll.initializeOrderedBulkOp();
var counter = 0;
coll.find({ width_px: { $type: "string" }}).forEach(function(data) {
    var updoc = {
        "$set": {}
    };
    updoc["$set"]["width_px"] = NumberInt(data.width_px);
    // 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 = coll.initializeOrderedBulkOp();
    }
    })
    // Add the rest in the queue
if (counter % 1000 != 0) bulk.execute();

It will construct a new NumberInt object that is mongodb specific, and it will be serialized as an int32.

其他提示

As per MongoDB documentation here From the Documents tab in MongoDB Compass, you can view, insert, clone, modify, and delete documents .

First you have to connect your mongod with MongoDB Compass then you shall able to change your desire data type of their respective field in MongoDB.

Change Field Type

You can change the data type of a field by using the data type selectors on the right of the field.

enter image description here

Note: Creating, deleting, editing and cloning documents is not permitted in MongoDB Compass Readonly Edition.

For your further ref here

change str to int

db.db-name.find({field-name: {$exists: true}}).forEach(function(obj) { 
obj.field-name = new NumberInt(obj.field-name);
db.db-name.save(obj); });
许可以下: CC-BY-SA归因
不隶属于 dba.stackexchange
scroll top