在更新触发器上组织 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;
  })