node.js - 使用 Firebase 云功能将所有文档从 Firestore 中的主集合复制到新的子集合
问题描述
我在 Firestore 中有一个包含几百个文档的主集合(几个月后将增长到几千个)。
我有一个用例,每次在 /users/ 集合中创建新的用户文档时,我都希望将 master 中的所有文档复制到 /users/{userId}/。
为此,我创建了一个 Firebase 云功能,如下所示:
// setup for new user
exports.setupCollectionForUser = functions.firestore
.document('users/{userId}')
.onCreate((snap, context) => {
const userId = context.params.userId;
db.collection('master').get().then(snapshot => {
if (snapshot.empty) {
console.log('no docs found');
return;
}
snapshot.forEach(function(doc) {
return db.collection('users').doc(userId).collection('slave').doc(doc.get('uid')).set(doc.data());
});
});
});
这行得通,唯一的问题是,只有大约 200 个文档需要很长时间(约 3-5 分钟)。这真是太糟糕了,因为很大程度上取决于这些文件被复制的速度。我希望这最多不超过几秒钟。此外,这些文件完全显示出来,而不是像它们写的那样,或者至少看起来是这样。
我做错什么了吗?为什么要花这么长时间?
有没有办法可以将此操作分解为多次读取和写入,以便我可以保证在几秒钟内获得最少的文档,而不是等到所有文档都被复制过来?
请指教。
解决方案
如果我没记错的话,通过正确管理并行写入Promise.all()
并返回 Promises 链,它通常应该会提高速度。
尝试按如下方式调整您的代码:
exports.setupCollectionForUser = functions.firestore
.document('users/{userId}')
.onCreate((snap, context) => {
const userId = context.params.userId;
return db.collection('master').get().then(snapshot => {
if (snapshot.empty) {
console.log('no docs found');
return null;
} else {
const promises = [];
const slaveRef = db.collection('users').doc(userId).collection('slave');
snapshot.forEach(doc => {
promises.push(slaveRef.doc(doc.get('uid')).set(doc.data()))
});
return Promise.all(promises);
}
});
});
我建议您观看Firebase 视频系列中关于“JavaScript Promises”的 3 个视频,这些视频解释了为什么在后台触发的云函数中返回 Promise 或值是关键。
另请注意,如果您确定要保存在集合中的文档少于 500 个slave
,则可以使用批量写入。(您可以将它用于 500 多个文档,但是您必须管理不同批次的批量写入......)
推荐阅读
- node.js - Promise.all API 调用,区分哪个抛出错误,只拒绝一个
- python - 为什么在遍历数字列表时会出现此错误,然后弹出循环所在的当前变量?
- sql - 填写 IsoWeek 的月份
- javascript - 为什么一个状态变量更新而另一个不更新?
- c++ - C++ opencv 确定编译所需的库
- r - 将数据框字段传递给函数中的回归模型
- java - Java keytool (keytool) 未找到,请安装
- string - 向字符串添加新字符的不同格式的不同输出
- android - 布局验证与加载程序 android Studio 不同
- python - Python如何检查文件是否使用记事本打开