Обновление поля сбора базы данных Mongo из объекта в массив объектов

#mongodb

#mongodb

Вопрос:

Мне пришлось изменить одно из полей моей коллекции в MongoDB с объекта на массив объектов, содержащий много данных. Новые документы вставляются без каких-либо проблем, но при попытке получить старые данные они никогда не сопоставляются с исходным DTO правильно и приводят к ошибкам.

тема — это поле, которое было изменено в коллекции Students.

Мне было интересно, есть ли какой-нибудь способ обновить все записи, чтобы все они имели один и тот же тип данных, без потери каких-либо данных.

Старая версия Student:

 {
    "_id": "5fb2ae251373a76ae58945df",
    "isActive": true,
    "details": {
      "picture": "http://placehold.it/32x32",
      "age": 17,
      "eyeColor": "green",
      "name": "Vasquez Sparks",
      "gender": "male",
      "email": "vasquezsparks@orbalix.com",
      "phone": " 1 (962) 512-3196",
      "address": "619 Emerald Street, Nutrioso, Georgia, 6576"
    },
    "subject": 
      {
        "id": 0,
        "name": "math",
        "module": {
          "name": "Advanced",
          "semester": "second"
        }
      }
  }
  

Это необходимо обновить до новой версии следующим образом:

 {
    "_id": "5fb2ae251373a76ae58945df",
    "isActive": true,
    "details": {
      "picture": "http://placehold.it/32x32",
      "age": 17,
      "eyeColor": "green",
      "name": "Vasquez Sparks",
      "gender": "male",
      "email": "vasquezsparks@orbalix.com",
      "phone": " 1 (962) 512-3196",
      "address": "619 Emerald Street, Nutrioso, Georgia, 6576"
    },
    "subject": [
      {
        "id": 0,
        "name": "math",
        "module": {
          "name": "Advanced",
          "semester": "second"
        }
      },
      {
        "id": 1,
        "name": "history",
        "module": {
          "name": "Basic",
          "semester": "first"
        }
      },
      {
        "id": 2,
        "name": "English",
        "module": {
          "name": "Basic",
          "semester": "second"
        }
      }
    ]
  }
  

Я понимаю, что может быть способ переименовать старую коллекцию, создать новую и вставить данные на основе старой в новую. Мне было интересно найти какой-нибудь прямой путь.

Комментарии:

1. Здесь что-то не так. student: ["idDetails":{...} недопустимый объект. Вы имеете в виду student: [ {"idDetails": {...} } ] ? Я думаю, что форма, которую вы, возможно, пытаетесь использовать, больше похожа на эту: student: { idDetails: { ... }, subject: [ {modulefld1:val, modulefl2:val}, {mf1:val, mf2:val} ] }

2. Вы можете нарезать массив от первого до последнего объекта, или фильтр тоже может работать. Это может быть легко в зависимости от реальной структуры. Но нам нужно больше данных, мой друг

3. можете ли вы опубликовать образец документа из коллекции?

4. Извините за опечатку ранее, я обновил образец документа выше, обратите внимание, что в модуле есть много вложенных вложенных документов (полей), пропустил их, чтобы сделать его коротким здесь. @BuzzMoschetti; @Minsky; @wak786

Ответ №1:

Цель состоит в том, чтобы превратиться subject в массив из 1, если он еще не является массивом, в противном случае оставьте его в покое. Это поможет:

 update args are (predicate, actions, options).

db.foo.update(
// Match only those docs where subject is an object (i.e. not turned into array):
{$expr: {$eq:[{$type:"$subject"},"object"]}},   

// Actions: set subject to be an array containing $subject.  You MUST use the pipeline version
// of the update actions to correctly substitute $subject in the expression!
[  {$set: {subject: ["$subject"] }} ],

// Do this for ALL matches, not just first:                  
{multi:true});
  

Вы можете запускать этот конвертер снова и снова, потому что он будет игнорировать преобразованные документы.

Если цель состоит в том, чтобы преобразовать и добавить несколько новых объектов, сохранив первый, тогда мы можем настроить дополнительные объекты и объединить их в один массив следующим образом:

 var mmm = [ {id:8, name:"CORN"}, {id:9, name:"DOG"} ];

rc = db.foo.update({$expr: {$eq:[{$type:"$subject"},"object"]}},
                   [ {$set: {subject: {$concatArrays: [["$subject"], mmm]} }} ],
                   {multi:true});

  

Комментарии:

1. Огромное спасибо