Viktor
можно, конечно, сгенерить кучу $or'ов, но это будет неэффективно
Dmitriy
Да, тоже пока варианта на уровне выборки данных не вижу. :(
Значит сделаю фильтр на уровне приложения :)
Viktor
как вариант: храните данные в удобной для запросов форме и мапьте их на бекенде
Viktor
либо храните в документе и тот и другой вариант представления
yopp
yopp
в эту сторону смотртие
Alexander
Всем привет.
Есть охрененная база на 20Гб с множеством коллекций.
Необходимо пропатчить часть коллекций на предмет замены данных.
Скрипт для mongoshell не поддерживает async/await.
Правильным ли будет запустить цикл по массву коллекций и в цикле сделать bulkWrite?
function start (array) {
for (var index = 0; index < array.length; index++) {
const [collection, fields] = array[index]
const col = collection.split(':')
const query = {}
const params = {}
fields.forEach(field => {
if (field.replaceWith === '$unset') {
if (!params.$unset) params.$unset = {}
params.$unset[field.source] = ""
} else {
if (!params.$set) params.$set = {}
params.$set[field.source] = field.replaceWith
}
if (field.query) Object.assign(query, field.query)
})
const updateMany = {
filter: query,
update: params,
}
console.log('Updating ${collection}...')
// db.getCollection(col[0]).bulkWrite([{ updateMany }])
}
}
start(Object.entries(collections))
yopp
yopp
хотя зачем bulkWrite в этом случае не понятно
yopp
запрос вроде один
yopp
просто updateMany
yopp
в 4.0 я бы ещё в транзакцию завернул
yopp
3.6 в сессию
Alexander
yopp
https://docs.mongodb.com/manual/reference/method/Session/
но это вам позволит только узнать чем закончился updateMany
yopp
я настоятельно рекомендую не делать unset
Alexander
yopp
если вы сразу будете удалять поля, у вас не будет возможности откатить операцию
yopp
ничего не делать
yopp
оставить старое поле
yopp
и добавьте «версию»
yopp
какой-то признак что у вас схема поменялась
yopp
пруф?
yopp
в монге нет схем
Alexander
линк
Alexander
__v это же версия?
yopp
версия нужна вам, чтоб в случае ошибки вы знали какие документы у вас уже проконвертированы
yopp
вы делаете миграцию, но ваша миграция расчитывает только на удачное стечение обстоятельств
yopp
самый надежный вид миграций — индемпотентные миграции
yopp
чтоб добиться индемпотентности надо соблюдать одно простое правило: append only
yopp
в миграции вы никогда не удаляете или обновляете существующие данные/ключ, только добавляете новые ключи
yopp
тогда вы можете применять её сколько угодно раз и ничего не будет
Alexander
yopp
{
_id: ObjectId,
name: "Pyotr E. Korobochka",
birthday: "19700101"
}
=>
{
_id: ObjectId,
name: "Pyotr Korobochka",
birthday: "19700101",
_v: 1,
first_name: "Pyotr",
last_name: "Korobochka",
birthdate: ISODate("1970-01-01T00:00:00")
}
Alexander
то есть, надо просто инкрементить __v, верно?
yopp
yopp
надо не удалять и не модифицировать существующие данные
yopp
а только добавлять новые, в новые поля
yopp
_v это исключительно для удобства
Alexander
при создании документа __v всегда равен 0. При модификации я его могу только инкрементить. Или я затупляю?
yopp
да причём тут _v вообще
Alexander
а...
yopp
вы туда можете всё что угодно писать, главное чтоб у разных версий схем были разные значения
yopp
так-то и без версии можно
yopp
но это не очень удобно
Nick
yopp
_s тогда
Alexander
я понял. но, ведь это влечет к изменению всего кода приложения
yopp
так миграция и так влечёт за собой изменение логики работы приложения
yopp
но бонус такого подхода что legacy потребители данных будут продолжать работать
Alexander
yopp
что такое «90% к расширению»?
Alexander
yopp
второй бонус у вас приложение может продолжать работать пока конвертируются данные
yopp
т.е. вы можете используя _s выбирать какую логику применять
yopp
_s может быть не версиями, а флагами
yopp
это ещё лучше
yopp
тогда вы уходите от «версионности» и начинаете думать «фичами»
Alexander
что такое «90% к расширению»?
по крайней мере, в моем случае, миграции ведут к расширению функционала. а этот скрипт нужен, чтобы передать базу сторонним разработчикам без персональных данных
yopp
а почему бы просто не сделать mongodump с проекцией?
yopp
или обязательно в хранилище обезличить?
yopp
а, лол
yopp
https://jira.mongodb.org/browse/TOOLS-28
yopp
fields только в mongoexport есть ¯\_(ツ)_/¯
yopp
да, query это фильтр по документам в коллекции
yopp
в mongoexport есть параметр —fields в котором можно указать какие ключи из документа экспортировать
yopp
у меня сложилось ошибочное представление что этот параметр есть и в mongodump. а его там нет
Alexander
yopp
в этом случае делайте как планировали, но добавьте _s поле, чтоб можно было восстановить после ошибки
Alexander
yopp
ну и убедитесь что вы это делаете не на основной базе, если оригинальные данные необходимо сохранить
yopp
я бы в любом случае сделал бэкап перед такой операцией и по необходимости бы его уничтожил, когда анонимизация данных точно успешно завершилась
Alexander
ну и убедитесь что вы это делаете не на основной базе, если оригинальные данные необходимо сохранить
а то ))) на дампе
const session = db.getMongo().startSession();
db = session.getDatabase(db.getName());
function start(array) {
const updateManyArray = [];
for (var index = 0; index < array.length; index++) {
const [collection, fields] = array[index];
const col = collection.split(":");
const query = {};
const params = {};
fields.forEach(field => {
if (field.replaceWith === "$unset") {
if (!params.$unset) params.$unset = {};
params.$unset[field.source] = "";
} else {
if (!params.$set) params.$set = {};
params.$set[field.source] = field.replaceWith;
}
if (field.query) Object.assign(query, field.query);
});
updateManyArray.push({
updateMany: {
filter: query,
update: params
}
});
}
db.getCollection(col[0]).bulkWrite(updateManyArray)
}
start(Object.entries(collections));
yopp
в вашем случае bulkWrite не имеет смысла
yopp
если внутри updateManyArray запросы на всю коллекцию, никакого профита не будет, один головняк
Alexander
сделать как раньше, но с updateMany?