使用 mongoimport 将 csv 数据作为数组导入 mongodb
Import csv data as array in mongodb using mongoimport
我一直在尝试使用 mongoimport 将 csv 数据导入 mongodb。合集是这样的:
{
id:"122234343",
name: "name1",
children: ["222334444","333344444"]
}
我尝试的一种方法是创建 2 个 csv 文件 - 一个带有 id 和名称,另一个带有 id,children(如果 id 有两个 children,那么它将有两行)。使用 mongoimport 将数据导入两个不同的集合,然后在具有 children 数据的第二个集合中使用 foreach() 更新集合数据。
请建议是否有其他方法可以直接从 CSV 填充此 "children" 数组?
合集如下:
{
"_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 来导入
对我来说,最简单的方法是弄清楚如何为 mongoimport
is to simply create a collection then use mongoexport
设置 "CSV" 的格式,看看 CSV 格式应该是什么样子。
因此,从 shell:
创建您的文档
db.newcol.insert({
id:"122234343",
name: "name1",
children: ["222334444","333344444"]
})
然后退出 shell 和 运行 mongoexport
:
mongoexport -d test -c testcol --fields id,name,children --type csv > out.csv
这会将输出显示为:
id,name,children
122234343,name1,"[""222334444"",""333344444""]"
其中 "array" 用 "string" 表示并使用转义形式的引号 ""
。
现在是一个非常明确的地方可以使用 mongoimport
,所以现在 "import" 来测试:
mongoimport -d test -c newcol --headerline --type csv out.csv
Re-enter shell 并查看新集合中的文档:
db.newcol.findOne()
{
"_id" : ObjectId("59476924d6eb0b7d6ac37e02"),
"id" : 122234343,
"name" : "name1",
"children" : "[\"222334444\",\"333344444\"]"
}
所以一切都在那里,但是 children 被列为 "string" 而不是数组。但这并不是真正的问题,因为我们已经导入了数据,现在我们可以实际转换它了:
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 = [];
}
因此,这将通过 $type
查询运算符迭代导入到集合中的任何 BSON 类型为 "string" 的内容。
然后我们取字符串,把它拆分成一个数组,去掉其他字符只留下你想要的值。
使用 .bulkWrite()
您可以高效地提交这些更新,而不是为每个请求编写每个文档。它们实际上以 1000 个为一组发送到服务器。
最终结果是文档的原始格式:
db.testcol.findOne()
{
"_id" : ObjectId("5947652ccb237bd6e4e902a5"),
"id" : "122234343",
"name" : "name1",
"children" : [
"222334444",
"333344444"
]
}
这就是我的 "step by step" 如何计算 CSV 格式、导入它然后 "transform" 将数据转换为您需要的状态。
更简单的方法是格式化您的 csv 文件
根据您的示例,列名称应如下所示
id name children.0 children.1
或者,除了接受的答案之外,如果您有 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}}]);
});
我一直在尝试使用 mongoimport 将 csv 数据导入 mongodb。合集是这样的:
{
id:"122234343",
name: "name1",
children: ["222334444","333344444"]
}
我尝试的一种方法是创建 2 个 csv 文件 - 一个带有 id 和名称,另一个带有 id,children(如果 id 有两个 children,那么它将有两行)。使用 mongoimport 将数据导入两个不同的集合,然后在具有 children 数据的第二个集合中使用 foreach() 更新集合数据。
请建议是否有其他方法可以直接从 CSV 填充此 "children" 数组?
合集如下:
{
"_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 来导入
对我来说,最简单的方法是弄清楚如何为 mongoimport
is to simply create a collection then use mongoexport
设置 "CSV" 的格式,看看 CSV 格式应该是什么样子。
因此,从 shell:
创建您的文档db.newcol.insert({
id:"122234343",
name: "name1",
children: ["222334444","333344444"]
})
然后退出 shell 和 运行 mongoexport
:
mongoexport -d test -c testcol --fields id,name,children --type csv > out.csv
这会将输出显示为:
id,name,children
122234343,name1,"[""222334444"",""333344444""]"
其中 "array" 用 "string" 表示并使用转义形式的引号 ""
。
现在是一个非常明确的地方可以使用 mongoimport
,所以现在 "import" 来测试:
mongoimport -d test -c newcol --headerline --type csv out.csv
Re-enter shell 并查看新集合中的文档:
db.newcol.findOne()
{
"_id" : ObjectId("59476924d6eb0b7d6ac37e02"),
"id" : 122234343,
"name" : "name1",
"children" : "[\"222334444\",\"333344444\"]"
}
所以一切都在那里,但是 children 被列为 "string" 而不是数组。但这并不是真正的问题,因为我们已经导入了数据,现在我们可以实际转换它了:
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 = [];
}
因此,这将通过 $type
查询运算符迭代导入到集合中的任何 BSON 类型为 "string" 的内容。
然后我们取字符串,把它拆分成一个数组,去掉其他字符只留下你想要的值。
使用 .bulkWrite()
您可以高效地提交这些更新,而不是为每个请求编写每个文档。它们实际上以 1000 个为一组发送到服务器。
最终结果是文档的原始格式:
db.testcol.findOne()
{
"_id" : ObjectId("5947652ccb237bd6e4e902a5"),
"id" : "122234343",
"name" : "name1",
"children" : [
"222334444",
"333344444"
]
}
这就是我的 "step by step" 如何计算 CSV 格式、导入它然后 "transform" 将数据转换为您需要的状态。
更简单的方法是格式化您的 csv 文件
根据您的示例,列名称应如下所示
id name children.0 children.1
或者,除了接受的答案之外,如果您有 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}}]);
});