Firebase Firestore Web v9如何查询dms集合中含当前用户ID的文档
问题原因
Firebase Firestore 本身不支持对文档ID进行子串包含查询,仅支持前缀匹配的范围查询,因此你当前把拼接ID作为文档ID的设计,无法直接通过单条where语句查询所有包含当前用户ID的dms文档。
如果不想调整现有数据结构,只能全量拉取dms集合的所有文档后,在前端过滤出文档ID包含当前用户ID的条目,该方案仅适合数据量极小的测试场景,生产环境不推荐使用。
推荐生产环境解决方案
1. 调整数据结构
在dms集合的每个父文档中新增participants字段,存储对话双方的UID数组,同时在首次发送私聊消息时初始化该父文档:
import { doc, getDoc, setDoc, collection, addDoc, serverTimestamp } from "firebase/firestore"; import { db } from "你的firebase配置文件路径"; // 修改后的发送私聊消息逻辑,首次发送时初始化dms父文档 export const sentDirectMsg = async ({ toUid, currentUid, message, name }) => { const idPair = [currentUid, toUid].sort().join("_"); // 先判断dms父文档是否存在,不存在则初始化 const dmDocRef = doc(db, "dms", idPair); const dmDocSnap = await getDoc(dmDocRef); if (!dmDocSnap.exists()) { await setDoc(dmDocRef, { participants: [currentUid, toUid], lastActive: serverTimestamp(), // 可选字段,用于会话列表按最近活跃时间排序 }); } // 写入消息到子集合 const messagesColRef = collection(dmDocRef, "messages"); await addDoc(messagesColRef, { timestamp: serverTimestamp(), message, name, senderId: currentUid // 可选字段,方便后续渲染时区分消息发送方 }); };
2. 查询当前用户的所有私聊会话
直接用array-contains查询所有包含当前用户ID的dms文档即可:
import { collection, query, where, onSnapshot } from "firebase/firestore"; import { db } from "你的firebase配置文件路径"; // 获取当前登录用户ID const currentUser = useSelector(selectLoggedInUser); const currentUid = currentUser.id; // 构造查询条件 const dmSessionsQuery = query( collection(db, "dms"), where("participants", "array-contains", currentUid) ); // 监听会话数据实时变更 const unsubscribe = onSnapshot(dmSessionsQuery, (snapshot) => { // 得到所有和当前用户相关的私聊会话列表 const dmSessions = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); // 后续可遍历会话ID,拉取每个会话对应的messages子集合内容 console.log(dmSessions); });
注意事项
首次执行查询时如果Firestore报错提示缺少索引,直接点击报错信息里的索引创建链接,等待索引创建完成即可正常查询。
内容的提问来源于stack exchange,提问作者Eric Harutyunyan
相关产品推荐
相关产品推荐

