Подтвердить что ты не робот

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.

4b9b3361

Ответ 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
  1. Я нашел и заменил json, используя мою привилегированную утилиту для редактирования текста.

  2. Я реимпортировал отредактированный файл, отбросив старую коллекцию по пути:

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 }, иначе будет обновлен только первый соответствующий документ.