在更新触发器上组织 firebase 写入的最佳方式
Best way to organize firebase writes on update trigger
这个问题可能有多个正确答案,但这是我的问题:我在 firebase 中有一个用户文档,其中包含许多可以更新的字段,并且它们以不同的方式交互。如果更新了一个字段,则可能需要更改后端的另一个字段。如果满足条件,最好有一大堆 if 语句,每个语句都有自己的写入操作,或者,或者在函数末尾为所有可能更改的字段执行单个写入。如果一个字段没有改变,我将不得不把它的原始值写回它自己。这看起来很笨重,但另一个选择也是如此。我错过了第三种选择吗?这里的最佳做法是什么?
这是我所说的一个例子。一次更新一个字段是我现在所拥有的,看起来像这样:
export const userUpdate = functions.firestore
.document("users/{userID}")
.onUpdate(async (change) => {
const beforeData = change.before.data();
const afterData = change.after.data();
// user levels up and gets more HP
if(beforeData.userLevel != afterData.userLevel){
const newMaxHP = 15 + 5 * afterData.userLevel;
change.after.ref.update({
maxHp: newMaxHP
})
}
//update user rating
if (beforeData.numberOfRatings != afterData.numberOfRatings) {
const newRating = placerRating(beforeData.userRating, beforeData.numberOfRatings, afterData.latestRating);
change.after.ref.update({
userRating: newRating
})
}
//replenish user funds from zero
if (afterData.money == 0){
change.after.ref.update({
money: 20
})
}
如果我在一次写入中完成所有操作,则 if 语句会为变量赋值,但不会更新 firestore 文档。每个 if 语句都包含一个 else 语句,将变量分配给字段的原始值。最后会有一个这样的写:
change.after.ref.update({
maxHp: newMaxHP,
userRating: newRating,
money: 20
})
希望对您有所帮助。
[编辑以添加关于更新地图值的后续问题]
@Dharmaraj 的回答效果很好,但我在更新地图值时很难应用它。顺便说一句 - 我正在使用 Typescript。
在使用@Dharmaraj 的解决方案之前,我是这样做的:
admin.firestore().collection("users").doc(lastPlayerAttacker).update({
"equipped.weapon.usesLeft": admin.firestore.FieldValue.increment(-1)
});
使用更新对象,我正在这样尝试,但我收到错误“对象的类型为 'unknown'”
const lastPlayerUpdates:{[key:string]:unknown} = {};
lastPlayerUpdates.equipped.weapon.usesLeft = admin.firestore.FieldValue.increment(-1);
admin.firestore().collection("users").doc(lastPlayerAttacker).update(lastPlayerUpdates);
关于如何修复它有什么建议吗?
每次您调用 update()
,您需要支付 1 次写入操作的费用。最好将所有更新的字段累积在一个对象中,然后只更新文档一次,这样效率也会更高。尝试重构代码,如下所示:
export const userUpdate = functions.firestore
.document("users/{userID}")
.onUpdate(async (change) => {
const beforeData = change.before.data();
const afterData = change.after.data();
const updatedData = {};
// user levels up and gets more HP
if (beforeData.userLevel != afterData.userLevel) {
const newMaxHP = 15 + 5 * afterData.userLevel;
updatedData.maxHp = newMaxHP;
}
//update user rating
if (beforeData.numberOfRatings != afterData.numberOfRatings) {
const newRating = placerRating(beforeData.userRating, beforeData.numberOfRatings, afterData.latestRating);
updatedData.userRating = newRating;
}
//replenish user funds from zero
if (afterData.money == 0) {
updatedData.money = 20;
}
await change.after.ref.update(updatedData);
console.log("Data updated");
return null;
})
这个问题可能有多个正确答案,但这是我的问题:我在 firebase 中有一个用户文档,其中包含许多可以更新的字段,并且它们以不同的方式交互。如果更新了一个字段,则可能需要更改后端的另一个字段。如果满足条件,最好有一大堆 if 语句,每个语句都有自己的写入操作,或者,或者在函数末尾为所有可能更改的字段执行单个写入。如果一个字段没有改变,我将不得不把它的原始值写回它自己。这看起来很笨重,但另一个选择也是如此。我错过了第三种选择吗?这里的最佳做法是什么?
这是我所说的一个例子。一次更新一个字段是我现在所拥有的,看起来像这样:
export const userUpdate = functions.firestore
.document("users/{userID}")
.onUpdate(async (change) => {
const beforeData = change.before.data();
const afterData = change.after.data();
// user levels up and gets more HP
if(beforeData.userLevel != afterData.userLevel){
const newMaxHP = 15 + 5 * afterData.userLevel;
change.after.ref.update({
maxHp: newMaxHP
})
}
//update user rating
if (beforeData.numberOfRatings != afterData.numberOfRatings) {
const newRating = placerRating(beforeData.userRating, beforeData.numberOfRatings, afterData.latestRating);
change.after.ref.update({
userRating: newRating
})
}
//replenish user funds from zero
if (afterData.money == 0){
change.after.ref.update({
money: 20
})
}
如果我在一次写入中完成所有操作,则 if 语句会为变量赋值,但不会更新 firestore 文档。每个 if 语句都包含一个 else 语句,将变量分配给字段的原始值。最后会有一个这样的写:
change.after.ref.update({
maxHp: newMaxHP,
userRating: newRating,
money: 20
})
希望对您有所帮助。
[编辑以添加关于更新地图值的后续问题]
@Dharmaraj 的回答效果很好,但我在更新地图值时很难应用它。顺便说一句 - 我正在使用 Typescript。
在使用@Dharmaraj 的解决方案之前,我是这样做的:
admin.firestore().collection("users").doc(lastPlayerAttacker).update({
"equipped.weapon.usesLeft": admin.firestore.FieldValue.increment(-1)
});
使用更新对象,我正在这样尝试,但我收到错误“对象的类型为 'unknown'”
const lastPlayerUpdates:{[key:string]:unknown} = {};
lastPlayerUpdates.equipped.weapon.usesLeft = admin.firestore.FieldValue.increment(-1);
admin.firestore().collection("users").doc(lastPlayerAttacker).update(lastPlayerUpdates);
关于如何修复它有什么建议吗?
每次您调用 update()
,您需要支付 1 次写入操作的费用。最好将所有更新的字段累积在一个对象中,然后只更新文档一次,这样效率也会更高。尝试重构代码,如下所示:
export const userUpdate = functions.firestore
.document("users/{userID}")
.onUpdate(async (change) => {
const beforeData = change.before.data();
const afterData = change.after.data();
const updatedData = {};
// user levels up and gets more HP
if (beforeData.userLevel != afterData.userLevel) {
const newMaxHP = 15 + 5 * afterData.userLevel;
updatedData.maxHp = newMaxHP;
}
//update user rating
if (beforeData.numberOfRatings != afterData.numberOfRatings) {
const newRating = placerRating(beforeData.userRating, beforeData.numberOfRatings, afterData.latestRating);
updatedData.userRating = newRating;
}
//replenish user funds from zero
if (afterData.money == 0) {
updatedData.money = 20;
}
await change.after.ref.update(updatedData);
console.log("Data updated");
return null;
})