Массовое изменение для типа поля в MongoDB - PullRequest
0 голосов
/ 05 июля 2018

Мне нужно изменить тип поля с int32 на строку. Это изменение касается данных на сервере и огромного количества документов.

С помощью простого обновления, подобного следующему, только небольшая часть документов обновляется из-за проблем со временем:

db.collection.find({"identifier": {$exists:true}})
    .forEach( function(x) {
        db.collection.update({_id: x._id}, {$set: {"identifier": 
        x.identifier.toString()}});
    }
);

Поэтому я решил сделать массовое изменение:

var bulk = db.collection.initializeUnorderedBulkOp();
bulk.find({"identifier": {$exists:true}}).update(
    function(x) {
        {_id: x._id}, {$set: {"identifier": x.identifier.toString()}}
    });
bulk.execute();

Но выдает ошибку и не выполняется.

Как мне сделать обновление, чтобы основная масса работала?

1 Ответ

0 голосов
/ 15 августа 2018

Нет массового обновления, где вы можете определить функцию в официальном документах . Что вы можете сделать сами, так это воссоздать массовую операцию, используя skip и limit .

Чтобы это работало, вам нужно определить значения пропуска и ограничения, которые вы хотите использовать. Если вы собираетесь выполнять обновление с использованием размера пакета 100, тогда предел всегда будет равен 100, но пропуск будет увеличиваться на 100 при каждом выполнении запроса.

Ex, первый запуск.

db.collection.find({"identifier": {$exists:true}}).sort({_id:1}).skip(0).limit(100)
    .forEach( function(x) {
        db.collection.update({_id: x._id}, {$set: {"identifier": 
        x.identifier.toString()}});
    }
);

Ex, второй запуск.

db.collection.find({"identifier": {$exists:true}}).sort({_id:1}).skip(100).limit(100)
    .forEach( function(x) {
        db.collection.update({_id: x._id}, {$set: {"identifier": 
        x.identifier.toString()}});
    }
);

Ex, третий прогон.

db.collection.find({"identifier": {$exists:true}}).sort({_id:1}).skip(200).limit(100)
    .forEach( function(x) {
        db.collection.update({_id: x._id}, {$set: {"identifier": 
        x.identifier.toString()}});
    }
);

Таким образом, вы можете контролировать, что делается для каждой партии размером 100.

Не забудьте ВСЕГДА сортировать перед пропуском и ограничением, иначе вы могли бы получить случайные результаты в операции пропуска. Вы можете сортировать по любым критериям.

Вы также можете помочь процессу, если операция поиска отфильтровывает результаты, которые необходимо преобразовать:

db.collection.find({"identifier": {$exists:true, $not {$type: "string"} }})
.forEach( function(x) {
            db.collection.update({_id: x._id}, {$set: {"identifier": 
            x.identifier.toString()}});
        }
    );

Но не объединяйте оба подхода, выберите один или другой (из-за результатов операции поиска).

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...