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保存到个人数组中。若数组存储方式不够理想,也欢迎提供更好的实现建议。
解决方案
错误原因分析
- 用户ID属性错误:Firebase Auth用户对象的唯一标识是
uid,而非id,你代码中使用userAuth.id会导致路径无效,触发类型错误。 - 集合创建逻辑错误: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
相关产品推荐
相关产品推荐

