扩展 Firebase Firestore 计划事件
Posted
技术标签:
【中文标题】扩展 Firebase Firestore 计划事件【英文标题】:Scaling firebase firestore scheduled event 【发布时间】:2019-09-24 16:23:08 【问题描述】:我有一个每 4 小时运行一次的 pubsub 活动。我想在预定活动之后保存所有用户的团队。我是批量写入,但批量写入每次提交的写入限制为 500 次。下面是一个类似于我正在尝试做的示例代码。
问题:如何自动扩展批量写入。
exports.updateNews = functions.pubsub
.topic("my-scheduled-topic")
.onPublish(message =>
return axios
.get(
"https://newsapi.org/v2/top-headlines?apiKey=someKey&sources=espn-cric-info"
)
.then(result =>
const batch = db.batch();
result.data.articles.forEach(article =>
const docRef = db.collection("news").doc();
batch.set(docRef, article);
);
return batch.commit();
)
.then(result =>
console.log(result);
return result;
)
.catch(error =>
console.log(error);
return error;
);
);
【问题讨论】:
【参考方案1】:如果您的批次遇到 500 次写入的限制,您可以改用 Promise.all()
,如下所示。当add()
方法调用返回的所有承诺都已解决时,它将返回一个解决的承诺。
exports.updateNews = functions.pubsub
.topic("my-scheduled-topic")
.onPublish(message =>
return axios
.get(
"https://newsapi.org/v2/top-headlines?apiKey=someKey&sources=espn-cric-info"
)
.then(result =>
const promises = [];
result.data.articles.forEach(article =>
promises.push(db.collection("news").add(article));
);
return Promise.all(promises);
)
.then(results =>
console.log(results);
return null;
)
.catch(error =>
console.log(error);
return null;
);
);
【讨论】:
Ty 再次我正在考虑对我昨天的问题发表评论。你能看看我发布的答案吗?代码正在运行,并且进行了多次批量写入,我只是不希望它失败。如果我能改进它,需要建议。 我对 Promise 还不满意,这就是为什么我试图避免它们的原因,我的 Linter 尖叫着说我不应该嵌套 Promise。 @Abdul-RafayShaikh 实际上,如果您使用 Firebase 异步任务,就无法避免承诺! :-) 我知道一开始可能有点“吓人”,但是如果你花时间研究 Promise,它们并没有那么复杂! :-) PS:我在建议的答案中添加了一些 cmets。我认为您应该尝试上述建议的答案。【参考方案2】:我想我自己解决了需要专家意见:
我知道我的问题代码看起来不像我在提问之前简化了问题的答案。
\\\ reference the collection I wanted to save to or the place I wanna write
var userTeamsSave = db.collection("saveTeams");
\\\ api call
db.collection("news")
.get()
.then(querySnapshot =>
\\\ create Json array from query snapshot
let users = [];
querySnapshot.forEach(user =>
users.push( id: user.id, data: user.data() );
);
return users;
)
.then(users =>
var counter = 0;
var commitCounter = 0;
var batches = [];
\\\ array of batches
batches[commitCounter] = db.batch();
users.forEach(user =>
\\\ limit batch write in 1 commit upto 499
if (counter <= 200)
var thisRef = userTeamsSave.doc(user.id);
batches[commitCounter].set(thisRef, user.data);
counter = counter + 1;
else
\\\\ Reset Counter
counter = 0;
thisRef = userTeamsSave.doc(user.id);
batches[commitCounter].set(thisRef, user.data);
commitCounter = commitCounter + 1;
batches[commitCounter] = db.batch();
);
\\\ return all batches
return batches;
)
.then(fullBatch =>
fullBatch.forEach(batch =>
console.count("wrote batch");
\\\ commit all batches
return batch.commit();
);
return;
)
.catch(error =>
console.error(error);
return error;
);
【讨论】:
要回复您的审查请求,恕我直言,我至少看到以下几点:对于 1/ 您需要返回对 db.collection("news").get() 的调用 2/ 您不需要做 return users;).then() 因为你没有在这里返回 Promise。 3/ 退货批次相同; 4/ 而不是 fullBatch.forEach();你需要使用 Promise.all()以上是关于扩展 Firebase Firestore 计划事件的主要内容,如果未能解决你的问题,请参考以下文章
Firebase:Firestore 未在 Cloud Function 的计划函数中更新数据
用于聊天应用的 Firebase 实时数据库或 Firestore? [关闭]
在中国使用 Firebase 身份验证和 Firestore