我正在编写基于Nodejs的脚本,将大型csv文件导入ibmcloudant数据库。我对这个脚本的方法如下:
- Script1:使用FTP连接从远程服务器下载ZIP文件
- Script1:遍历下载的zip文件并从中提取CSV文件
- Script1:使用文件读写流将每个CSV文件上传到AWS S3存储桶
- Script2:连接到S3 bucket,并迭代在特定bucket位置找到的每个CSV文件
- Script2:使用流读取CSV文件,并通过管道将其转换为JSON格式的CSV数据
- 脚本2:连接到IBMcloudant数据库
- Script2:通过发出GET请求,对每个JSON对象逐一检查现有的cloudant文档
- Script2:若找到文档,则使用JSON对象进行更新,否则将条目作为新文档创建到cloudant中,并为其单独请求API
- 脚本2:如果所有CSV数据成功迁移到cloudant数据库,则从S3 bucket中删除CSV文件
目前有效的方法:
- 从FTP下载ZIP文件从ZIP提取CSV文件并上传到S3 bucket
- 如果我们只是在终端上打印每个转换后的JSON对象,那么将CSV文件作为流读取并使用npm包"csvtojson"将其转换为JSON对象就像魅力一样
- 成功连接到IBM cloudant数据库
面临的问题:
- 在一个循环中,试图在cloudant中为每个JSON对象检查现有记录,但它没有超过几个记录,最终会出现与内存/堆相关的错误。此外,它还存在cloudant速率限制的问题,当在循环中进行查找和导入操作时,该限制很快就会饱和
精确错误:
- 致命错误:无效的标记压缩接近堆限制分配失败-JavaScript堆内存不足
- IBM Cloudant上的请求太多
备注:
- FTP服务器上可能存在多个ZIP文件
- ZIP文件中可能有多个CSV文件
- 我一直试图导入的一个CSV文件由大约130万条记录组成,文件大小大约为300MB
- 对于我来说,没有任何选择可以考虑提高IBMCloudant的速率限制来满足这一要求
有人能建议在不面临我上面提到的问题的情况下解决这一要求的最佳方法吗?任何解决这一要求的替代npm方案也最受欢迎。任何改变我的发展方式的建议也非常受欢迎。
假设您的CSV行是按id排序的,您可以首先进行批量获取:
请求:
POST /db/_all_docs HTTP/1.1
Accept: application/json
Content-Length: 70
Content-Type: application/json
Host: localhost:5984
{
"keys" : [
"a_id123",
"b_id123",
"c_id123",
"d_id123",
]
}
然后,您将得到以下内容:响应
{
"total_rows" : 2666,
"rows" : [
{
"value" : {
"rev" : "1-a3544d296de19e6f5b932ea77d886942"
},
"id" : "a_id123",
"key" : "a_id123"
},
{
"value" : {
"rev" : "1-91635098bfe7d40197a1b98d7ee085fc"
},
"id" : "b_id123",
"key" : "b_id123"
}
],
"offset" : 0
}
现在,您可以循环浏览响应,查看哪些文档存在,哪些文档不存在。
在此之后,您可以批量添加不存在的文档:
请求:
POST /db/_bulk_docs HTTP/1.1
Accept: application/json
Content-Length: 109
Content-Type:application/json
Host: localhost:5984
{
"docs": [
{
"_id": "c_id123",
"foo": "bar",
},
{
"_id": "d_id123",
"foo": "bar c",
},
{
"_id": "a_id123",
"_rev": "1-a3544d296de19e6f5b932ea77d886942",
"foo": "updated",
}
]
}
批量获取文档:https://docs.couchdb.org/en/stable/api/database/bulk-api.html#post--数据库_all_docs
批量创建/更新文档:https://docs.couchdb.org/en/stable/api/database/bulk-api.html#db-批量文档