Импорт данных 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 для импорта