Firestore如何实现以UID为子集合名存储多分类文档
问题描述
我的数据库根目录有一个userCategories集合,应用中用户可添加名称唯一的分类,每个分类文档结构如下:
{ createdAt: Timestamp.now(), categoryName: userDefinedCategoryName, color: randomColorCode }
我期望的数据库结构为:
root- |-userCollection |-uid1 |-uid2 |-userCategories |-uid1 |-{createdAt:...,categoryName:"...",color:"..."} |-{createdAt:...,categoryName:"...",color:"..."} |-uid2 |-{createdAt:...,categoryName:"...",color:"..."}
当前我使用以下代码:
const categoryDocRef = doc(db, "userCategories", uid); await setDoc( categoryDocRef, { createdAt: Timestamp.now(), categoryName: category, color: color }).then(() => { return { success: true, errorMessage: "" }; });
但这只能在每个UID下创建单个文档,无法实现如uid1那样存储多个分类。
我尝试过另一种写法:
const categoryDocRef = doc(db, "userCategories", uid); const colRef = collection(categoryDocRef, "Anything Here") await addDoc( colRef, { createdAt: Timestamp.now(), categoryName: category, color: color }).then(() => { console.log(`User document for uid:${uid}`); return { success: true, errorMessage: "" }; });
但这会生成多余的嵌套层级:
|-userCategories |-uid1 |-anything here |-firebase generated id |-{createdAt:...,categoryName:"...",color:"..."} |-{createdAt:...,categoryName:"...",color:"..."}
我认为“firebase generated id”或“anything here”层级是多余的,可直接使用categoryName或自动生成ID来避免额外嵌套。请问是否有方法实现预期的结构?
解决方案
Firestore的层级规则是集合→文档→子集合→文档,要实现你预期的结构,有两种简洁的方案:
方案1:以UID作为子集合名称,分类文档直接存放在该子集合下
这种方案完全匹配你想要的结构,直接把每个用户的UID作为userCategories下的子集合名称,分类文档直接存入这个子集合(可以用自动生成ID或唯一的categoryName作为文档ID)。
代码示例(用自动生成ID):
// 直接创建以uid命名的子集合 const userCategoriesCol = collection(db, "userCategories", uid); // 在子集合中添加分类文档 await addDoc(userCategoriesCol, { createdAt: Timestamp.now(), categoryName: category, color: color }).then(() => { return { success: true, errorMessage: "" }; });
生成的结构:
root- |-userCategories |-uid1(子集合) |-自动生成ID文档1 |-{createdAt:...,categoryName:"...",color:"..."} |-自动生成ID文档2 |-{createdAt:...,categoryName:"...",color:"..."} |-uid2(子集合) |-自动生成ID文档1 |-{createdAt:...,categoryName:"...",color:"..."}
代码示例(用categoryName作为文档ID,需保证名称唯一):
const categoryDocRef = doc(db, "userCategories", uid, category); await setDoc(categoryDocRef, { createdAt: Timestamp.now(), categoryName: category, color: color }).then(() => { return { success: true, errorMessage: "" }; });
生成的结构:
root- |-userCategories |-uid1(子集合) |-"分类1"文档 |-{createdAt:...,categoryName:"分类1",color:"..."} |-"分类2"文档 |-{createdAt:...,categoryName:"分类2",color:"..."}
方案2:扁平化结构,所有分类直接存放在userCategories集合中
如果不想用嵌套子集合,可以把所有分类文档直接放在userCategories集合里,每个文档额外携带uid字段,查询时通过uid过滤即可。
代码示例:
const categoryDocRef = doc(db, "userCategories"); // 自动生成文档ID await setDoc(categoryDocRef, { uid: uid, createdAt: Timestamp.now(), categoryName: category, color: color }).then(() => { return { success: true, errorMessage: "" }; });
查询用户分类的示例:
const querySnapshot = await getDocs( query(collection(db, "userCategories"), where("uid", "==", uid)) ); // 处理查询结果 querySnapshot.forEach(doc => { console.log(doc.data()); });
内容的提问来源于stack exchange,提问作者Fergus Johnson
相关产品推荐
相关产品推荐

