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

如何在Firebase中避免重复添加已存在的Coin至coins集合?

嘿,这个问题我之前也碰到过,其实核心就是要先确认用户有没有已经关注过这个币种,再决定要不要往数据库里加~ 你现在每次点击都用doc()生成新的随机文档ID,哪怕是同一个币种同一个用户,也会重复创建记录,咱们来改改逻辑:

解决思路:先检查再操作

我们需要把点击处理函数改成异步的,先查询数据库里是否存在当前用户关注该币种的记录,再分情况执行添加/删除(毕竟按钮应该是「关注/取消关注」的切换逻辑对吧?)

方案1:用查询判断是否已存在

const handleClick = async () => {
  const currentUser = firebase.auth().currentUser;
  // 先处理用户未登录的情况,避免报错
  if (!currentUser) {
    alert('请先登录后再进行关注操作');
    return;
  }
  const userId = currentUser.uid;

  // 查询当前用户是否已关注该币种
  const querySnapshot = await db.collection("coins")
    .where("userId", "==", userId)
    .where("id", "==", price.id)
    .get();

  if (!following) {
    // 当前未关注:如果没有记录才添加
    if (querySnapshot.empty) {
      const data = { 
        following: true,
        logo_url: price.logo_url, 
        id: price.id, 
        name: price.name, 
        price: price.price, 
        userId: userId 
      }; 
      await db.collection("coins").add(data);
    }
    // 更新按钮状态
    setTitle("Following");
    setFollowing(true);
  } else {
    // 当前已关注:删除对应的记录
    if (!querySnapshot.empty) {
      querySnapshot.forEach(doc => doc.ref.delete());
    }
    setTitle("Follow");
    setFollowing(false);
  }
};

方案2:用自定义文档ID(更高效)

上面的查询方案需要每次点击都查数据库,更高效的方式是用「用户ID+币种ID」作为文档的唯一ID,这样直接通过文档ID就能判断是否存在,不用走查询:

const handleClick = async () => {
  const currentUser = firebase.auth().currentUser;
  if (!currentUser) {
    alert('请先登录后再进行关注操作');
    return;
  }
  const userId = currentUser.uid;
  // 生成唯一文档ID,确保同一用户同一币种只会有一条记录
  const docId = `${userId}_${price.id}`;
  const docRef = db.collection("coins").doc(docId);

  if (!following) {
    const docSnapshot = await docRef.get();
    // 只有当文档不存在时才添加
    if (!docSnapshot.exists) {
      const data = { 
        following: true,
        logo_url: price.logo_url, 
        id: price.id, 
        name: price.name, 
        price: price.price, 
        userId: userId 
      }; 
      await docRef.set(data);
    }
    setTitle("Following");
    setFollowing(true);
  } else {
    // 已关注就删除文档
    await docRef.delete();
    setTitle("Follow");
    setFollowing(false);
  }
};

额外小提示

如果用方案1的查询逻辑,记得去Firestore控制台给coins集合创建复合索引(userId和id的组合索引),这样查询速度会更快哦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:36:21