我正在使用GCP CLI中的简单节点脚本从CSV将16,000条记录导入Firestore。
CSV文件有四个列,每个列都作为集合中的新文档写入。我必须异步处理CSV,因为从CSV写入的每一行都链接到上一行中的数据。因此,导入需要5个小时以上。
该过程连续失败,并出现以下错误: 错误:16未经授权:请求具有无效的身份验证凭据。预期的OAuth 2访问令牌,登录cookie或其他有效的身份验证凭据。
我怀疑这是因为这是一个长时间的异步任务,因此身份验证令牌即将过期。根据我的阅读,身份验证令牌的使用寿命为1小时。
我在下面简化了代码,以模拟CVS导入问题。在Google Cloud Platform命令行中运行时,会重现该错误。
const {Firestore} = require('@google-cloud/firestore');
const db = new Firestore();
var previous = '';
async function processRecord(record) {
console.log(record);
console.log(record);
let collectionRef = db.collection('groups');
const snapshot = await collectionRef.where('name', '==', 'World').get();
let data = {
name: record,
previous: previous,
created: Firestore.Timestamp.now()
}
let docRef = await db.collection('testing').add(data);
previous = docRef.id;
}
async function importCsv(csvFileName) {
var records = [];
for(var i = 0; i < 16000; i++) {
records.push(`Filler: ${i}`);
}
// const fileContents = await readFile(csvFileName, 'utf8');
// const records = await parse(fileContents, { columns: true });
for (const record of records) {
await processRecord(record);
}
console.log(`Processed ${records.length} records`);
}
importCsv(process.argv[2]).catch(e => console.error(e));
我该怎么做才能完成导入?
答案 0 :(得分:1)
编辑:给出了更多详细信息(代码示例和要求的更好描述)后,修改了整个答案
避免由于auth令牌过期而导致的错误的最佳方法是更快地加载(16k的5小时是太多时间)。这可以通过多种方式实现,但是在查看了提供的代码之后,我创建了两个nodejs脚本,这些脚本可以满足您创建“反向链接列表”的需求,而无需花费超过一分钟的时间来加载整个16k记录集。
说明:创建记录并在同一事务中读取它是一种缓慢的方法,最好创建记录,然后查询完整的数据集并相应地进行更新。另外,强烈建议使用批处理进行写入和更新操作,因为服务器端库会并行化各个写入,有关更多信息,请参见下一个链接:Batched writes:
对于批量数据输入,请使用具有并行并行写入操作的服务器客户端库。批处理写入的性能优于串行写入,但不优于并行写入。您应该使用服务器客户端库进行批量数据操作,而不要使用移动/网络SDK。
脚本:第一部分是加载整个数据集,我使用了代码中提供的虚拟加载来举例说明这一点,但是您可以将记录变量替换为csv中加载的行文件。另外请注意,我使用数字索引来填充previous
字段,这对于继续跟踪加载记录的顺序非常重要。
batch_writing.js
const {Firestore} = require('@google-cloud/firestore');
const firestore = new Firestore();
async function batch_writting() {
var records = [];
let writeBatch = firestore.batch();
for(var i = 0; i < 17000; i++) {
records.push(`Filler: ${i}`);
}
let index = 0;
for (const record of records) {
let documentRef = firestore.collection('testing').doc();
let data = {
name: record,
previous: index,
created: Firestore.Timestamp.now()
}
writeBatch.create(documentRef,data);
if((index+1) % 500 === 0){
writeBatch.commit().then(() => {
console.log('Successfully executed batch.');
}).catch(e => console.error(e));
writeBatch = firestore.batch();
}
index++;
}
writeBatch.commit().then(() => {
console.log('Successfully executed batch.');
}).catch(e => console.error(e));
}
batch_writting().catch(e => console.error(e));
在完成写作部分并为previous
字段填充了递增索引之后,我们可以继续查询最近创建的完整数据集,并继续使用正确的< em>文档ID 从上一行开始加载。这是通过按previous
字段对查询进行排序来完成的,该字段填充了增量索引。请注意,由于第一条记录没有先前加载的行,因此其数值将为0。
update_writing.js
previous
如果您需要查询更多字段或其他集合,请随时更改脚本,但请记住避免查询特定字段,而应选择收集完整数据集的查询。另外,如果您需要其他文字,则建议使用批处理文字。