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

Firebase/Firestore创建用户时如何创建嵌套收藏集合?

问题:Firebase/Firestore中无法为认证用户创建嵌套收藏集合

我希望在Firebase/Firestore中为已认证用户创建一个嵌套集合,用于保存其收藏内容。尝试在创建用户的同时创建该集合以便后续读写,但始终无法成功。可以正常创建用户,但无法同时创建另一个集合;尝试在用户点击收藏按钮时创建集合,两种情况均触发类型错误:Uncaught (in promise) TypeError: n is undefined

我的创建用户代码:

//This function creates a new user. If the user already exists, no new document will be created
export const createUserDocumentFromAuth = async (
  userAuth,
  additionalInfo = {}
) => {
  if (!userAuth) return;

  const userDocRef = doc(db, 'users', userAuth.uid); //database instance, collection, identifier
  const bookmarkRef = doc(db, 'users', userAuth.id, 'bookmarks'); //This triggers error
  const userSnapshot = await getDoc(userDocRef);
  if (!userSnapshot.exists()) {
    //If user snapshot doesn't exist - create userDocRef
    const { displayName, email } = userAuth;
    const createdAt = new Date();

    try {
      await setDoc(userDocRef, {
        displayName,
        email,
        createdAt,
        ...additionalInfo,
      });
      setDoc(bookmarkRef, { //Try to create a bookmarks collection here
        favorites: []
      })
    } catch (error) {
      console.log('Error creating user', error.message);
    }
  }
  //if user data exists
  return userDocRef;
};

点击收藏按钮的代码:

export const addBookmarkForUser = async (userAuth, showId) => {
  const bookmarkRef = doc(db, 'users', userAuth.id, 'bookmarks');
  try {
    await setDoc(bookmarkRef, {
      favorites: showId
    });
  }catch(error){
    console.log('error creating bookmark', error.message)
  } 
};

我是Firebase/Firestore新手,仅需实现用户点击按钮时将物品ID保存到个人数组中。若数组存储方式不够理想,也欢迎提供更好的实现建议。


解决方案

错误原因分析

  1. 用户ID属性错误:Firebase Auth用户对象的唯一标识是uid,而非id,你代码中使用userAuth.id会导致路径无效,触发类型错误。
  2. 集合创建逻辑错误:Firestore中无法直接创建集合,必须通过创建集合下的具体文档来间接生成集合。你试图直接给bookmarks集合调用setDoc,但doc()方法只能指向具体文档,不能指向集合。

修改后的代码

1. 创建用户时初始化收藏文档

export const createUserDocumentFromAuth = async (
  userAuth,
  additionalInfo = {}
) => {
  if (!userAuth) return;

  const userDocRef = doc(db, 'users', userAuth.uid);
  // 正确路径:users/{uid}/bookmarks/{固定文档ID},通过创建文档生成集合
  const bookmarkDocRef = doc(db, 'users', userAuth.uid, 'bookmarks', 'userFavorites');
  const userSnapshot = await getDoc(userDocRef);

  if (!userSnapshot.exists()) {
    const { displayName, email } = userAuth;
    const createdAt = new Date();

    try {
      await setDoc(userDocRef, {
        displayName,
        email,
        createdAt,
        ...additionalInfo,
      });
      // 创建bookmarks集合下的文档,间接生成该集合
      await setDoc(bookmarkDocRef, {
        favorites: []
      });
    } catch (error) {
      console.log('Error creating user', error.message);
    }
  }
  return userDocRef;
};

2. 点击收藏按钮时添加ID到数组(自动去重)

import { doc, updateDoc, arrayUnion } from "firebase/firestore";

export const addBookmarkForUser = async (userAuth, showId) => {
  if (!userAuth) return;
  const bookmarkDocRef = doc(db, 'users', userAuth.uid, 'bookmarks', 'userFavorites');
  try {
    // 使用arrayUnion避免重复添加ID
    await updateDoc(bookmarkDocRef, {
      favorites: arrayUnion(showId)
    });
  } catch (error) {
    console.log('error creating bookmark', error.message)
  } 
};

存储方案优化建议

  • 数组存储:适合收藏数量少、仅需简单ID列表的场景,优点是简洁易读,但要注意Firestore单文档最大1MB的限制,收藏过多会超出容量。
  • 独立文档存储:如果需要给收藏添加元数据(如添加时间)、支持单独删除/查询单条收藏,建议把每个收藏作为bookmarks集合下的独立文档:
    // 添加收藏时创建独立文档,用showId作为文档ID
    const bookmarkDocRef = doc(db, 'users', userAuth.uid, 'bookmarks', showId);
    await setDoc(bookmarkDocRef, {
      showId: showId,
      addedAt: new Date()
    });
    
    这种方式支持分页、排序,也更容易管理单条收藏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:20:29