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

Firebase实时数据库无法删除指定条目及数据结构异常问题

解决Firebase Realtime Database的三个问题:无法删除条目、数据结构异常、控制台警告

问题概述

我需要在Firebase Realtime Database中创建如下数据结构:

"users": { 
  "JkaThVRqp1cBbKxLBk0UzUtu1tJ3": { 
    "email": "fwwfw@mail.de",        
    "username": "efwfw",        
    "favorite teams": [        
      "team1", "team2", "team3"        
    ]
  }
}

但目前遇到三个问题:

  • 无法删除"favorite teams"数组:通过控制台或终端删除后,内容会自动重新出现
  • 实际生成的数据结构不符合预期:
    实际结构:
    "UID":{"favoriteTeams":{"favoriteTeam":"team","team"}}
    
    预期结构:
    "UID":{"favoriteTeams":["team","team"]}
    
  • 控制台抛出警告:

    [Warning] [2024-04-27T11:18:37.683Z] @firebase/database: (firebase-database.js, line 1)
    "FIREBASE WARNING: Exception was thrown by user callback. @http://127.0.0.1:5500/resource/javascript/index.js:139:45
    onValue@https://www.gstatic.com/firebasejs/10.11.0/firebase-database.js:1:157844
    exceptionGuard@https://www.gstatic.com/firebasejs/10.11.0/firebase-database.js:1:19287
    eventListRaise@https://www.gstatic.com/firebasejs/10.11.0/firebase-database.js:1:142783
    eventQueueRaiseQueuedEventsMatchingPredicate@https://www.gstatic.com/firebasejs/10.11.0/firebase-database.js:1:142509
    eventQueueRaiseEventsAtPath@https://www.gstatic.com/firebasejs/10.11.0/firebase-database.js:1:142131
    repoAddEventCallbackForQuery@https://www.gstatic.com/firebasejs/10.11.0/firebase-database.js:1:169823
    addEventListener@https://www.gstatic.com/firebasejs/10.11.0/firebase-database.js:1:169849
    @http://127.0.0.1:5500/resource/javascript/index.js:136:12 "

相关代码

HTML部分

<div>
        <select id="region" name="Bundesland Auswahl" title="Bundesland">
          <option value="" disabled selected>Select a Region</option>
          <option value="rg1">Region 1</option>
        </select>
        <select name="club" id="team" title="team">
          <option value="" disabled selected>Select a team</option>
        </select>
        <button id="submit" name="newEntry" value="newEntry">Submit</button>
</div>

JavaScript部分

document.getElementById("submit").addEventListener("click", function (e) {
  e.preventDefault();

  const teamSelect = document.getElementById("team");
  const newFavoriteTeams = Array.from(
    teamSelect.selectedOptions,
    (option) => option.value
  );

  const auth = getAuth();
  const user = auth.currentUser;

  if (user) {
    const userId = user.uid;
    const favoriteTeamsRef = ref(database, `users/${userId}/favoriteTeams`);

    onValue(favoriteTeamsRef, (snapshot) => {
      const existingFavoriteTeams = snapshot.val() || [];
      const updatedFavoriteTeams = [
        ...new Set([...existingFavoriteTeams, ...newFavoriteTeams]),
      ];

      update(favoriteTeamsRef, { favoriteTeams: updatedFavoriteTeams })
        .then(() => {
          alert("Favorite teams updated successfully.");
        })
        .catch((error) => {
          alert("Error");
        });
    });
  } else {
    alert("No user is signed in.");
  }
});

Firebase安全规则

{
  "rules": {
    ".read": false,
    ".write": false,
    "users": {
      "$uid": {
        ".read": "auth.uid === $uid",
        ".write": "auth.uid === $uid || !data.exists()"
      }
    },
    "vereine": {
      ".read": true,
      ".write": true
    },
    "spiele": {
      ".read": true,
      ".write": true
    }
  }
}

解决方案

1. 修复数据结构异常与控制台警告

原JS代码存在两个核心问题:

  • 使用onValue持续监听数据变化,导致每次更新后触发回调,形成循环写入,这也是删除后数据自动恢复的原因
  • update的目标路径与参数不匹配:favoriteTeamsRef已经指向users/${userId}/favoriteTeams,却传入{favoriteTeams: updatedFavoriteTeams},导致嵌套结构

修改后的JS代码:

document.getElementById("submit").addEventListener("click", async function (e) {
  e.preventDefault();

  const teamSelect = document.getElementById("team");
  const newFavoriteTeams = Array.from(
    teamSelect.selectedOptions,
    (option) => option.value
  );

  const auth = getAuth();
  const user = auth.currentUser;

  if (user) {
    const userId = user.uid;
    const userRef = ref(database, `users/${userId}`);
    try {
      // 仅获取一次用户数据,避免持续监听
      const snapshot = await get(userRef);
      const existingData = snapshot.val() || {};
      // 确保现有数据是数组类型,避免非数组导致的扩展运算符报错
      const existingFavoriteTeams = Array.isArray(existingData.favoriteTeams) 
        ? existingData.favoriteTeams 
        : [];
      // 合并并去重
      const updatedFavoriteTeams = [...new Set([...existingFavoriteTeams, ...newFavoriteTeams])];
      
      // 直接更新用户节点下的favoriteTeams字段为数组
      await update(userRef, { favoriteTeams: updatedFavoriteTeams });
      alert("Favorite teams updated successfully.");
    } catch (error) {
      alert(`Error: ${error.message}`);
    }
  } else {
    alert("No user is signed in.");
  }
});

2. 解决无法删除数组的问题

修复代码后,停止了不必要的持续监听,此时删除操作不会被代码自动恢复。删除favoriteTeams的方式有两种:

  • 清空数组:await update(userRef, { favoriteTeams: [] })
  • 删除整个字段:await remove(ref(database, users/${userId}/favoriteTeams))

3. 安全规则验证

当前安全规则中,users/$uid的写入权限为auth.uid === $uid || !data.exists(),允许用户创建自己的节点,且仅本人可更新,规则无问题。确保操作时用户已登录,否则会触发权限错误。

内容的提问来源于stack exchange,提问作者Wyral 468B

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 08:15:09