MongoDB переименовать базу данных в массиве
Мне нужно переименовать indentifier
в этом:
{ "general" :
{ "files" :
{ "file" :
[
{ "version" :
{ "software_program" : "MonkeyPlus",
"indentifier" : "6.0.0"
}
}
]
}
}
}
Я пробовал
db.nrel.component.update(
{},
{ $rename: {
"general.files.file.$.version.indentifier" : "general.files.file.$.version.identifier"
} },
false, true
)
но он возвращает: $rename source may not be dynamic array
.
Ответы
Ответ 1
Как уже упоминалось в документации, нет возможности напрямую переименовывать поля внутри массивов с помощью одной команды. Ваш единственный вариант - перебрать ваши документы коллекции, прочитать их и обновить каждый с помощью $unset old/$set new operations.
Ответ 2
Для того, что стоит, хотя это звучит ужасно, но это решение довольно просто. Это, конечно, зависит от того, сколько записей у вас есть. Но вот мой пример:
db.Setting.find({ 'Value.Tiers.0.AssetsUnderManagement': { $exists: 1 } }).snapshot().forEach(function(item)
{
for(i = 0; i != item.Value.Tiers.length; ++i)
{
item.Value.Tiers[i].Aum = item.Value.Tiers[i].AssetsUnderManagement;
delete item.Value.Tiers[i].AssetsUnderManagement;
}
db.Setting.update({_id: item._id}, item);
});
Я перебираю свою коллекцию, где найден массив, и "неправильное" имя найдено. Затем я перебираю вспомогательную коллекцию, устанавливаю новое значение, удаляю старый и обновляю весь документ. Это было относительно безболезненно. Конечно, у меня есть только несколько десятков тысяч строк для поиска, из которых только несколько десятков соответствуют критериям.
Тем не менее, я надеюсь, что этот ответ поможет кому-то!
Изменить: добавлен snapshot()
в запрос. Посмотрите, почему в комментариях.
Вы должны применить моментальный снимок() к курсору перед извлечением любых документов из базы данных. Вы можете использовать только snapshot() с нечеткими коллекциями.
Ответ 3
У меня была аналогичная проблема. В моей ситуации я нашел следующее намного проще:
- Я экспортировал коллекцию в json:
mongoexport --db mydb --collection modules --out modules.json
-
Я нашел и заменил json, используя мою привилегированную утилиту для редактирования текста.
-
Я реимпортировал отредактированный файл, отбросив старую коллекцию по пути:
mongoimport --db mydb --collection modules --drop --file modules.json
Ответ 4
Я также хотел бы переименовать свойство в массиве: и я использовал thaht
db.getCollection('YourCollectionName').find({}).snapshot().forEach(function(a){
a.Array1.forEach(function(b){
b.Array2.forEach(function(c){
c.NewPropertyName = c.OldPropertyName;
delete c["OldPropertyName"];
});
});
db.getCollection('YourCollectionName').save(a)
});
Ответ 5
Начиная с Mongo 4.2
, db.collection.update()
может принять конвейер агрегации, что в конечном итоге позволяет обновить поле на основе его собственного значения:
// { general: { files: { file: [
// { version: { software_program: "MonkeyPlus", indentifier: "6.0.0" } }
// ] } } }
db.collection.update(
{},
[{ $set: { "general.files.file": {
$map: {
input: "$general.files.file",
as: "file",
in: {
version: {
software_program: "$$file.version.software_program",
identifier: "$$file.version.indentifier" // fixing the typo here
}
}
}
}}}],
{ multi: true }
)
// { general: { files: { file: [
// { version: { software_program: "MonkeyPlus", identifier: "6.0.0" } }
// ] } } }
Буквально, это update
документирует путем (пере) $set
массива "general.files.file"
помощью $map
проверяя его элементы "file"
in
объекте "version"
содержащем то же поле "software_program"
и переименованное поле "identifier"
который содержит то, что раньше было значением "indentifier"
.
Пара дополнительных деталей:
-
Первая часть {}
- это запрос на совпадение, который фильтрует, какие документы обновлять (в данном случае все документы).
-
Вторая часть [{ $set: { "general.files.file": {... }}}]
представляет собой конвейер агрегации обновлений (обратите внимание на квадратные скобки, обозначающие использование конвейера агрегации):
-
$set
- это новый оператор агрегирования, который в этом случае заменяет значение массива "general.files.file"
. - Используя операцию
$map
, мы заменяем все элементы из массива "general.files.file"
в основном на те же элементы, но с полем "identifier"
а не "indentifier"
: -
input
массив для отображения. -
as
имя переменной, присвоенной зацикленным элементам -
in
- фактическое преобразование, примененное к элементам. В этом случае он заменяет элементы объектом "version"
состоящим из полей "software_program"
и "identifier"
. Эти поля заполняются путем извлечения их предыдущих значений с использованием нотации $$file.xxxx
(где file
- это имя, данное элементам из части as
).
-
Не забудьте { multi: true }
, иначе будет обновлен только первый соответствующий документ.