我有一个非常大的ASCII平面文件(150万行)需要读取。它基本上是制造商提供的零件清单。我想使用Firestore托管它。
作为.csv文件,其最大容量为250GB。我能够使用Windows PowerShell将其转换为JSON文件,现在它的重量超过1GB。
如何将这些数据导入Firestore?我认为Admin SDK和批处理写入将是一种方法。因此,我完成了所有设置并组装了一个节点脚本,但是Firestore的Admin SDK文档很薄。
我的节点脚本在下面,但是抛出错误FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
var admin = require("firebase-admin");
var serviceAccount = require("./--------------------------.json");
var fs = require('fs');
var myCsvFile = "./global.csv"
var parse = require('csv-parse');
require('should');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://g--------b.firebaseio.com"
});
var firestore = admin.firestore();
var writeBatch = firestore.batch();
var myRef = firestore.collection("foo").doc();
var obj = {};
fs.createReadStream(myCsvFile)
.pipe(parse({delimiter: '|',relax_column_count:true,quote: ''}))
.on('data', function(csvrow) {
if(csvrow[1]){
obj.family = csvrow[1];
}
if(csvrow[2]){
obj.series = csvrow[2];
}
if(csvrow[3]){
obj.sku = csvrow[3];
}
if(csvrow[5]){
obj.description = csvrow[5];
}
if(csvrow[7]){
obj.price = csvrow[7];
}
writeBatch.set(myRef, obj);
})
.on('end',function() {
writeBatch.commit()
});
答案 0 :(得分:1)
在规定的范围内进行批量写入不会对您造成任何问题。我认为您目前没有其他选择。
答案 1 :(得分:1)
500个条目。因此,关键是将.commit
的速率限制为每秒1,并将batch.set
的速率限制为每次提交500以下。我使用aynch / await作为速率限制器,以及将promise.all
推入.set
es递增数组的.batch
样式模式。
哦,还有最后一件事-我不得不告诉节点--max-old-space-size
开关使用更多的内存。
以下脚本是从High Tech Telecom复制的:
var admin = require("firebase-admin"); var serviceAccount = require("./your-firebase-project-service-account-key.json"); var fs = require('fs'); var csvFile = "./my-huge-file.csv" var parse = require('csv-parse'); require('should'); admin.initializeApp({ credential: admin.credential.cert(serviceAccount), databaseURL: "https://your-project.firebaseio.com" }); var firestore = admin.firestore(); var thisRef; var obj = {}; var counter = 0; var commitCounter = 0; var batches = []; batches[commitCounter] = firestore.batch(); fs.createReadStream(csvFile) .pipe( parse({delimiter: '|',relax_column_count:true,quote: ''}) ) .on('data', function(csvrow) { if(counter <= 498){ if(csvrow[1]){ obj.family = csvrow[1]; } if(csvrow[2]){ obj.series = csvrow[2]; } if(csvrow[3]){ obj.sku = csvrow[3]; } if(csvrow[4]){ obj.description = csvrow[4]; } if(csvrow[6]){ obj.price = csvrow[6]; } thisRef = firestore.collection("your-collection-name").doc(); batches[commitCounter].set(thisRef, obj); counter = counter + 1; } else { counter = 0; commitCounter = commitCounter + 1; batches[commitCounter] = firestore.batch(); } }) .on('end',function() { writeToDb(batches); }); function oneSecond() { return new Promise(resolve => { setTimeout(() => { resolve('resolved'); }, 1010); }); } async function writeToDb(arr) { console.log("beginning write"); for (var i = 0; i < arr.length; i++) { await oneSecond(); arr[i].commit().then(function () { console.log("wrote batch " + i); }); } console.log("done."); }
答案 2 :(得分:0)
简短说明:您永远不会重置obj(obj = {}),因此基本上您一直都在插入相同的记录。