使用 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}}]);     
});