循环查询Firestore文档遇问题,已尝试常规方案仍未解决
问题解决:Firebase嵌套查询无法正确返回结果
问题描述
我参考过其他人的解决方案,但还是没搞定。需求是先从eventPeople集合(集合A)查询指定用户的文档,再遍历每个文档,根据文档里的eventId去events集合(集合B)查询对应的事件。试过async/await和结合Promise.all()的.then写法,都没得到正确结果。
原代码
export const getUserEvents = async (req: Request, res: Response) => { console.log("getUserEvents:req.params.userId: ", req.params.userId); try { let events: Event[] = []; const snapshot = await db.collection("eventPeople").where("userId", "==", req.params.userId).get(); snapshot.forEach(async (doc) => { const eventRef = await db.collection("events").where("eventId", "==", doc.data().eventId).get(); eventRef.forEach((eventDoc) => { console.log("event: ", eventDoc.data()) }); }); console.log("events: ", events) return res.json({ events: events }); } catch (err) { functions.logger.error("unable to query eventPeople using userId", { userId: req.params.userId, error: err }); } return res.json({ events: "events" }); };
问题根源
forEach不支持异步等待:snapshot.forEach里传入的是async函数,但forEach会直接遍历执行,不会等待每个异步查询完成。代码会直接走到打印和返回响应的逻辑,此时异步查询还没结束,events数组依然是空的。- 未正确填充结果数组:原代码只打印了事件数据,没有把数据添加到
events数组中,就算异步查询完成,也无法返回有效结果。
修复方案
把snapshot转换成数组,用Promise.all统一处理所有异步查询,等所有请求完成后再收集结果:
export const getUserEvents = async (req: Request, res: Response) => { console.log("getUserEvents:req.params.userId: ", req.params.userId); try { const snapshot = await db.collection("eventPeople").where("userId", "==", req.params.userId).get(); // 将每个文档的查询任务转为Promise,存入数组 const eventPromises = snapshot.docs.map(async (doc) => { const eventData = doc.data(); const eventSnapshot = await db.collection("events").where("eventId", "==", eventData.eventId).get(); // 返回查询到的第一个事件(如果eventId唯一) return eventSnapshot.docs[0]?.data() as Event; }); // 等待所有Promise完成,拿到完整事件数组 const events = await Promise.all(eventPromises); // 过滤掉可能的undefined(比如eventId不存在的情况) const validEvents = events.filter(event => event !== undefined); console.log("events: ", validEvents); return res.json({ events: validEvents }); } catch (err) { functions.logger.error("unable to query eventPeople using userId", { userId: req.params.userId, error: err }); // 出错时返回错误响应 return res.status(500).json({ error: "Failed to fetch user events" }); } };
额外优化建议
- 如果
eventId是events集合的文档ID,不需要用where查询,直接用db.collection("events").doc(eventData.eventId).get(),查询效率更高。 - 可以考虑做数据冗余(比如在
eventPeople里存储事件的关键信息),或者使用Firebase的集合组查询,减少嵌套查询的次数,提升接口性能。
内容的提问来源于stack exchange,提问作者Garrett
相关产品推荐
相关产品推荐

