如何在Firestore中同时查询文档及子文档并满足指定条件?
Firestore 查询符合条件的 Posts 文档
前提说明
Firestore 原生不支持直接通过父集合查询过滤子集合的文档存在性,所以需要通过以下两种方式实现需求:
方案一:分步查询(适合小结果集)
先筛选满足前三个条件的帖子,再逐个校验子集合中是否存在用户投票记录:
- 执行基础条件查询
const userUID = "当前用户的UID"; const targetCategories = ["分类A", "分类B"]; // 你的指定分类列表 // 先获取满足前三个条件的帖子 const baseQuery = db.collection("posts") .where("author", "!=", userUID) .where("author choice", "==", null) .where("category", "in", targetCategories);
- 遍历结果,检查子集合
const validPosts = []; const querySnapshot = await baseQuery.get(); for (const postDoc of querySnapshot.docs) { // 检查当前用户是否在该帖子的votes子集合中有记录 const voteDoc = await db.collection(`posts/${postDoc.id}/votes`).doc(userUID).get(); if (!voteDoc.exists) { validPosts.push({ id: postDoc.id, ...postDoc.data() }); } } // validPosts 即为符合所有条件的帖子数据
注意:如果基础查询返回大量结果,会产生较多额外读请求,影响性能和成本,仅推荐用于结果集较小的场景。
方案二:反向存储字段(推荐)
在 post 文档中新增一个数组字段(比如 votedUserIDs),存储所有已投票用户的UID,这样可以直接通过一次查询完成过滤:
- 投票时维护字段
用户投票/取消投票时,同步更新post文档的votedUserIDs数组:
// 投票时添加用户UID await db.collection("posts").doc(postId).update({ votedUserIDs: firebase.firestore.FieldValue.arrayUnion(userUID) }); // 取消投票时移除用户UID await db.collection("posts").doc(postId).update({ votedUserIDs: firebase.firestore.FieldValue.arrayRemove(userUID) });
- 执行完整条件查询
const userUID = "当前用户的UID"; const targetCategories = ["分类A", "分类B"]; // 一次查询筛选所有条件 const finalQuery = db.collection("posts") .where("author", "!=", userUID) .where("author choice", "==", null) .where("category", "in", targetCategories) .where("votedUserIDs", "array-contains-not", userUID); // 获取结果 const validPostsSnapshot = await finalQuery.get(); const validPosts = validPostsSnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
注意:array-contains-not 操作符不能与其他数组操作符(如 array-contains、in)同时使用,如果有其他数组过滤需求,可以改用 where("votedUserIDs", "not-in", [userUID]),但 not-in 最多支持10个元素。
内容的提问来源于stack exchange,提问作者user15782390
相关产品推荐
相关产品推荐

