MongoDB: как изменить тип поля?

в Stackoverflow уже есть вопрос, очень похожий на мой вопрос. Дело в том, что ответ на эти вопросы был для драйвера Java, я пытаюсь сделать это в оболочке.

Я делаю это...

db.meta.update({'fields.properties.default': { $type : 1 }}, {'fields.properties.default': { $type : 2 }})

Это не работает!

12 ответов


единственный способ изменить $type данные для обновления данных, где данные имеют правильный тип.

в этом случае, похоже, вы пытаетесь изменить $type от 1 (двойной) до 2 (строка).

поэтому просто загрузите документ из БД, выполните приведение (new String(x)), а затем снова сохраните документ.

Если вам нужно сделать это программно и полностью от оболочки, вы можете использовать find(...).forEach(function(x) {}) синтаксис.


в ответ на второй комментарий ниже. Изменить поле bad от числа до строки в коллекции foo.

db.foo.find( { 'bad' : { $type : 1 } } ).forEach( function (x) {   
  x.bad = new String(x.bad); // convert field to string
  db.foo.save(x);
});

преобразовать строковое поле в integer:

db.db-name.find({field-name: {$exists: true}}).forEach(function(obj) { 
    obj.field-name = new NumberInt(obj.field-name);
    db.db-name.save(obj);
});

преобразовать целое поле в строку:

db.db-name.find({field-name: {$exists: true}}).forEach(function(obj) {
    obj.field-name = "" + obj.field-name;
    db.db-name.save(obj);
});

для преобразования string в int.

db.my_collection.find().forEach( function(obj) {
    obj.my_value= new NumberInt(obj.my_value);
    db.my_collection.save(obj);
});

для строки для двойного преобразования.

    obj.my_value= parseInt(obj.my_value, 10);

для поплавка:

    obj.my_value= parseFloat(obj.my_value);

db.coll.find().forEach(function(data) {
    db.coll.update({_id:data._id},{$set:{myfield:parseInt(data.myfield)}});
})

то, что действительно помогло мне изменить тип объекта в MondoDB, было просто этой простой строкой, возможно, упомянутой выше...:

db.Users.find({age: {$exists: true}}).forEach(function(obj) {
    obj.age = new NumberInt(obj.age);
    db.Users.save(obj);
});

пользователи-это моя коллекция, а age-объект, который имел строку вместо целого числа (int32).


преобразовать int32 в строку в mongo без создания массива просто "добавить" к вашему номеру : -)

db.foo.find( { 'mynum' : { $type : 16 } } ).forEach( function (x) {   
  x.mynum = x.mynum + ""; // convert int32 to string
  db.foo.save(x);
});

чтобы преобразовать поле строкового типа в поле даты, вам нужно будет повторить курсор, возвращаемый find() способ использования forEach() метод, в цикле преобразовать поле в объект даты, а затем обновить поле с помощью $set оператора.

использовать массовый API для массовых обновлений, которые предлагают лучше производительность, поскольку вы будете отправлять операции на сервер партиями, скажем, 1000, что дает вам лучшую производительность, поскольку вы не отправляете каждый запрос на сервер, только один раз в каждые 1000 запросов.

следующий пример демонстрирует этот подход, в первом примере используется массовый API, доступный в версиях MongoDB >= 2.6 and < 3.2. Он обновляет все документы в коллекции, изменив все created_at поля для полей типа "дата":

var bulk = db.collection.initializeUnorderedBulkOp(),
    counter = 0;

db.collection.find({"created_at": {"$exists": true, "$type": 2 }}).forEach(function (doc) {
    var newDate = new Date(doc.created_at);
    bulk.find({ "_id": doc._id }).updateOne({ 
        "$set": { "created_at": newDate}
    });

    counter++;
    if (counter % 1000 == 0) {
        bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
        bulk = db.collection.initializeUnorderedBulkOp();
    }
})
// Clean up remaining operations in queue
if (counter % 1000 != 0) { bulk.execute(); }

следующий пример применяется к новой версии MongoDB 3.2, которая с устарел массовый API и предоставлен новый набор API, используя bulkWrite():

var bulkOps = [];

db.collection.find({"created_at": {"$exists": true, "$type": 2 }}).forEach(function (doc) { 
    var newDate = new Date(doc.created_at);
    bulkOps.push(         
        { 
            "updateOne": { 
                "filter": { "_id": doc._id } ,              
                "update": { "$set": { "created_at": newDate } } 
            }         
        }           
    );     
})

db.collection.bulkWrite(bulkOps, { "ordered": true });

Мне нужно изменить тип данных нескольких полей в коллекции, поэтому я использовал следующее, чтобы сделать несколько изменений типа данных в коллекции документов. Ответа на старый вопрос, но может быть полезным для других.

db.mycoll.find().forEach(function(obj) { 

    if (obj.hasOwnProperty('phone')) {
        obj.phone = "" + obj.phone;  // int or longint to string
    }

    if (obj.hasOwnProperty('field-name')) {
     obj.field-name = new NumberInt(obj.field-name); //string to integer
    }

    if (obj.hasOwnProperty('cdate')) {
        obj.cdate = new ISODate(obj.cdate); //string to Date
    }

    db.mycoll.save(obj); 
});

You can easily convert the string data type to numerical data type.
Don't forget to change collectionName & FieldName.
for ex : CollectionNmae : Users & FieldName : Contactno.

попробуйте выполнить этот запрос..

db.collectionName.find().forEach( function (x) {
x.FieldName = parseInt(x.FieldName);
db.collectionName.save(x);
});

Я использую этот скрипт в консоли mongodb для преобразования string в float...

db.documents.find({ 'fwtweaeeba' : {$exists : true}}).forEach( function(obj) { 
        obj.fwtweaeeba = parseFloat( obj.fwtweaeeba ); 
        db.documents.save(obj); } );    

db.documents.find({ 'versions.0.content.fwtweaeeba' : {$exists : true}}).forEach( function(obj) { 
        obj.versions[0].content.fwtweaeeba = parseFloat( obj.versions[0].content.fwtweaeeba ); 
        db.documents.save(obj); } );

db.documents.find({ 'versions.1.content.fwtweaeeba' : {$exists : true}}).forEach( function(obj) { 
        obj.versions[1].content.fwtweaeeba = parseFloat( obj.versions[1].content.fwtweaeeba );  
        db.documents.save(obj); } );

db.documents.find({ 'versions.2.content.fwtweaeeba' : {$exists : true}}).forEach( function(obj) { 
        obj.versions[2].content.fwtweaeeba = parseFloat( obj.versions[2].content.fwtweaeeba );  
        db.documents.save(obj); } );

а это в php)))

foreach($db->documents->find(array("type" => "chair")) as $document){
    $db->documents->update(
        array('_id' => $document[_id]),
        array(
            '$set' => array(
                'versions.0.content.axdducvoxb' => (float)$document['versions'][0]['content']['axdducvoxb'],
                'versions.1.content.axdducvoxb' => (float)$document['versions'][1]['content']['axdducvoxb'],
                'versions.2.content.axdducvoxb' => (float)$document['versions'][2]['content']['axdducvoxb'],
                'axdducvoxb' => (float)$document['axdducvoxb']
            )
        ),
        array('$multi' => true)
    );


}

demo измените тип поля mid от string до mongo objectId с помощью mongoose

 Post.find({}, {mid: 1,_id:1}).exec(function (err, doc) {
             doc.map((item, key) => {
                Post.findByIdAndUpdate({_id:item._id},{$set:{mid: mongoose.Types.ObjectId(item.mid)}}).exec((err,res)=>{
                    if(err) throw err;
                    reply(res);
                });
            });
        });

Mongo ObjectId - это еще один пример таких стилей, как

Number, string, boolean, которые надеются, что ответ поможет кому-то другому.


все ответы до сих пор используют некоторую версию forEach, повторяя все элементы коллекции на стороне клиента.

однако вы можете использовать серверную обработку MongoDB с помощью aggregate pipeline и $out stage as:

этап $out атомарно заменяет существующую коллекцию на новая коллекция результатов.

пример:

db.documents.aggregate([
         {
            $project: {
               _id: 1,
               numberField: { $substr: ['$numberField', 0, -1] },
               otherField: 1,
               differentField: 1,
               anotherfield: 1,
               needolistAllFieldsHere: 1
            },
         },
         {
            $out: 'documents',
         },
      ]);