Как обрабатывать изменения схемы "монгодб" в производстве
Я использую mondodb + node.js + mongoose.js ORM.
Скажем, у меня есть некоторый вложенный массив объекта без поля _id
mongoose.Schema({
nested: [{
_id: false, prop: 'string'
}]
})
И затем я хочу, чтобы объявление было полем для всех вложенных объектов, поэтому схема мангуста была бы
mongoose.Schema({
nested: [{
prop: 'string'
}]
})
Затем я должен запустить несколько script, чтобы изменить производственную БД, не так ли? Каков наилучший способ справиться с такими изменениями? Какой инструмент (или подход) лучше всего использовать для реализации изменения?
Ответы
Ответ 1
Одним из существенных преимуществ баз данных без схемы является то, что вам не нужно обновлять всю базу данных новыми макетами схемы. Если в некоторых документах в БД нет конкретной информации, тогда ваш код может сделать что-то подходящее или вместо этого выбрать что-нибудь с этой записью.
Другим вариантом является ленивое обновление документов по мере необходимости - только при повторном просмотре. В этом случае вы можете выбрать флаг для каждой записи/версии документа, который изначально может даже не отображаться (и, следовательно, означает "версия 0" ). Однако это необязательно. Вместо этого ваш код доступа к базе данных ищет требуемые данные, а если он не существует, поскольку это новая информация, добавленная после обновления кода, то она будет заполнять результаты в максимальной степени.
В вашем примере преобразование _id:false
в стандартное поле MongoId
, когда код читается (или записывается после обновления) и _id:false
в настоящее время установлен, затем выполните изменение и запишите его только когда это абсолютно необходимо.
Ответ 2
Вам действительно нужно написать script, который перейдет в коллекцию и добавит новое поле в каждый документ. Однако точный способ, как вы это сделаете, зависит от размера вашей базы данных и производительности вашей системы хранения. Добавление поля в документ изменит его размер и, следовательно, вызовет перемещение в большинстве случаев. Эта операция оказывает влияние на IO и также ограничивается им. Если ваша коллекция составляет всего несколько тысяч документов, может быть до ста тысяч, то вы можете просто перебирать ее в одном цикле, потому что вся коллекция, вероятно, вписывается в память, и все IO произойдет потом. Однако, если коллекция охватывает далеко за пределами доступной памяти, то подход более сложный. Мы обычно следуем следующим шагам в производственном использовании MongoDB:
- Открыть курсор с таймаутом = False
- Прочитайте фрагмент документов в памяти
- Запустить запросы обновления для этих документов
- Сон в течение некоторого времени, чтобы избежать перегрузки подсистемы IO и нанесения вреда производственному приложению
- Повторить до конца
- Закрыть курсор:)
Размер блока документов и период сна должны определяться экспериментально. Обычно вы хотите избежать QR/QW в монгостатах на период миграции. Для больших коллекций на более медленных дисках (например, EBS на Amazon) этот IO-безопасный подход может занимать от нескольких часов до нескольких дней.