You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止Firestore数值字段变为负数并获取更新前的原始值

解决方案

方案1:客户端事务+前置校验(推荐)

直接读取目标文档的当前shares值做校验,同时用Firestore事务保证操作原子性,避免并发更新导致的数据不一致问题。
修正后的代码如下:

function sellStock() {
  // 先匹配到对应股票的文档ID
  db.collection("Stocks")
    .where("ticker", "==", props.name)
    .get()
    .then((querySnapshot) => {
      if (!querySnapshot.empty) {
        querySnapshot.forEach(async function (doc) {
          const stockRef = db.collection("myStocks").doc(doc.id);
          // 开启事务做原子校验+更新
          try {
            await db.runTransaction(async (t) => {
              const stockDoc = await t.get(stockRef);
              // 此处获取的就是更新前的旧持仓数量
              const currentShares = stockDoc.data().shares;
              // 前置校验,持仓不足直接抛出错误终止更新
              if (currentShares < amount) {
                throw new Error("持仓数量不足,无法卖出");
              }
              // 校验通过执行更新
              t.update(stockRef, {
                shares: currentShares - amount
              });
            });
            console.log("卖出操作执行成功");
          } catch (e) {
            console.log("操作失败:", e.message);
          }
        });
      }
    });
}

方案2:Firestore安全规则兜底(必加)

即使客户端被恶意篡改,安全规则也会拦截非法的更新请求,从服务端层面保证shares不会为负,规则配置如下:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /myStocks/{stockId} {
      allow update: if request.resource.data.shares >= 0
        && request.resource.data.shares <= resource.data.shares;
    }
  }
}

注意事项

  • 事务的作用是防止多个卖出请求同时执行时,先查出来的持仓还没更新,导致最后计算结果为负的并发问题
  • 两种方案建议同时使用:客户端校验降低无效请求,安全规则做最终兜底

内容的提问来源于stack exchange,提问作者BarakOren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 05:27:01