Импорт данных CSV в виде массива в mongodb с использованием mongoimport

Я пытался импортировать данные CSV в Mongodb с помощью Mongoimport. Коллекция выглядит так:

{
id:"122234343",
name: "name1",
children: ["222334444","333344444"]
}

Один из подходов, которые я попробовал, состоит в том, чтобы создать 2 CSV-файла - один с идентификатором и именем, а другой с идентификатором дочерние (если идентификатор имеет двух дочерних элементов, то он будет иметь две строки). Импортируйте данные в две разные коллекции, используя mongoimport, а затем используйте обновление данных коллекции, используя foreach() во второй коллекции, имеющей дочерние данные.

Пожалуйста, предложите, есть ли другой способ заполнить этот массив "children" напрямую из CSV??

4 ответа

Решение

Для меня самый простой способ понять, как отформатировать ваш "CSV" для mongoimport это просто создать коллекцию, а затем использовать mongoexport на нем, чтобы увидеть, как должен выглядеть формат CSV.

Итак, создайте свой документ из оболочки:

db.newcol.insert({
  id:"122234343",
  name: "name1",
  children: ["222334444","333344444"]
})

Затем выйдите из оболочки и запустите mongoexport:

 mongoexport -d test -c testcol --fields id,name,children --type csv > out.csv

Который покажет вам вывод как:

id,name,children
122234343,name1,"[""222334444"",""333344444""]"

Где "массив" представлен "строкой" и с использованием кавычек "" в их спасшейся форме.

Это сейчас довольно понятное место для использования mongoimport от, так что просто "импорт" сейчас, чтобы проверить:

mongoimport -d test -c newcol --headerline --type csv out.csv

Повторно войдите в оболочку и посмотрите документ (ы) в новой коллекции:

db.newcol.findOne()
{
        "_id" : ObjectId("59476924d6eb0b7d6ac37e02"),
        "id" : 122234343,
        "name" : "name1",
        "children" : "[\"222334444\",\"333344444\"]"
}

Так что все есть, НО дети перечислены как "строка", а не как массив. Но на самом деле это не проблема, так как мы импортировали данные, и теперь нам нужно только преобразовать их:

var ops = [];
db.testcol.find({ "children": { "$type": 2} }).forEach(doc => {
  var children = doc.children.split(',').map( e => e.replace(/"|\[|\]|\\/gm,'').toString() );
  ops.push({
    "updateOne": {
      "filter": { "_id": doc._id },
      "update": { "$set": { "children": children } }
    }
  });

  if ( ops.length >= 1000 ) {
    db.newcol.bulkWrite(ops);
    ops = [];
  }             
});

if ( ops.length > 0 ) {
  db.newcol.bulkWrite(ops);
  ops = [];
}

Так что это будет повторять все, что было импортировано в коллекцию, которая имеет тип BSON 2, который является "строкой" через $type оператор запроса.

Затем мы берем строку, разделяем ее как массив и удаляем другие символы, оставляя только желаемое значение.

С помощью .bulkWrite() Вы фиксируете эти обновления эффективным способом, а не записываете каждый отдельный документ для каждого запроса. Они фактически отправляются партиями по 1000 на сервер.

Конечным результатом является документ в оригинальной требуемой форме:

db.testcol.findOne()
{
        "_id" : ObjectId("5947652ccb237bd6e4e902a5"),
        "id" : "122234343",
        "name" : "name1",
        "children" : [
                "222334444",
                "333344444"
        ]
}

Так что это мой "пошаговый" способ, как вы можете обработать свой формат CSV, импортировать его и затем "преобразовать" данные в состояние, в котором они вам нужны.

В качестве альтернативы и в дополнение к принятому ответу, если у вас есть embedded documents, просто импортируйте csv и используйте JSON.parseдля свойства со встроенными данными и обновления исходного документа, как в приведенном ниже примере кода:

      db.myCollectionName.find({ }).forEach(doc => {   
    // parse the embedded document
    var myPropertyValue = JSON.parse(doc.myPropertyName);   
    // update the original document, or push to a new collection, etc
    db.myCollectionName.updateOne({"_id": doc._id}, [ {$set:{ "myPropertyName" : myPropertyValue}}]);     
});

Более простой способ - отформатировать файл csv.

В соответствии с вашим примером имена столбцов должны выглядеть так

id имя children.0 children.1

Коллекция как ниже:

   {
       "_id" : ObjectId("580100f4da893943d393e909"),
       "username" : "crystal",
       "likes" : [ "running", "pandas", "software development" ]
    }

ниже команда для csv в mongodb:

mongoimport --db users --type csv --headerline --file /opt/backups/contacts.csv

на самом деле Mongodb не реляционная БД, поэтому нет необходимости создавать два CSV для импорта

Другие вопросы по тегам