如何在Node.js Express中获取Firestore子集合数据?
如何在Node.js Express中获取Firestore用户文档及其所有子集合数据?
我用Node.js Express做后端、React做前端开发了一个Web应用。Firestore数据库里有个users集合,里面的每个用户文档既有自身字段,也包含多个子集合,且所有用户的子集合结构一致(比如每个用户都有childGrow、childPrivateDetails、familyDetails、wenath这4个子集合)。我需要获取所有用户的文档字段,以及他们各自子集合里的字段数据,但当前接口返回的结果里没有子集合的内容,求解决方法。
现有代码
模型类
class Users { constructor(id,name,email,provider,firstWord,leda,age,birthday,district,gender,familyChildren,fatherEducation,monthlyIncome,motherEducation,whichChild,awaSE,awaUN,kathakaraaSE,kathakaraaSE,kathakaraaUN) { this.id = id; this.name = name; this.email = email; this.provider = provider; this.email = firstWord; this.email = leda; this.age = age; this.birthday = birthday; this.district = district; this.gender = gender; this.familyChildren = familyChildren; this.fatherEducation = fatherEducation; this.monthlyIncome = monthlyIncome; this.motherEducation = motherEducation; this.whichChild = whichChild; this.awaSE = awaSE; this.awaUN = awaUN; this.kathakaraaSE = kathakaraaSE; this.kathakaraaUN = kathakaraaUN; } } module.exports = Users;
控制器
'use strict'; const firebase = require('../db'); const Users = require('../models/users'); const firestore = firebase.firestore(); const getAllUsers = async (req, res, next) => { try { const users = await firestore.collection('users'); const data = await users.get(); const userArray = []; if(data.empty) { res.status(404).send('No user found'); }else { data.forEach(doc => { const users = new Users( doc.id, doc.data().name, doc.data().email, doc.data().provider, doc.data().firstWord, doc.data().leda, doc.data().age, doc.data().birthday, doc.data().district, doc.data().gender, doc.data().familyChildren, doc.data().fatherEducation, doc.data().monthlyIncome, doc.data().motherEducation, doc.data().whichChild, doc.data().awaSE, doc.data().awaUN, doc.data().kathakaraaSE, doc.data().kathakaraaUN, ); userArray.push(users); }); res.send(userArray); } } catch (error) { res.status(400).send(error.message); } } module.exports = { getAllUsers, }
路由类
const router = require("express").Router(); const { getAllUsers } = require('../controllers/userscontroller.js') router.get('/AllUsers', getAllUsers); module.exports = router;
当前问题
接口返回结果仅包含users集合的字段,子集合的数据完全缺失。
解决方案
1. 修正模型类错误并添加子集合属性
原模型类存在字段赋值错误(用firstWord和leda覆盖了email),同时需要添加子集合对应的属性来存储数据:
class Users { constructor(id, name, email, provider, firstWord, leda, age, birthday, district, gender, familyChildren, fatherEducation, monthlyIncome, motherEducation, whichChild, awaSE, awaUN, kathakaraaSE, kathakaraaUN) { this.id = id; this.name = name; this.email = email; this.provider = provider; // 修正赋值错误,不再覆盖email this.firstWord = firstWord; this.leda = leda; this.age = age; this.birthday = birthday; this.district = district; this.gender = gender; this.familyChildren = familyChildren; this.fatherEducation = fatherEducation; this.monthlyIncome = monthlyIncome; this.motherEducation = motherEducation; this.whichChild = whichChild; this.awaSE = awaSE; this.awaUN = awaUN; this.kathakaraaSE = kathakaraaSE; this.kathakaraaUN = kathakaraaUN; // 添加子集合属性,用于存储对应数据 this.childGrow = {}; this.childPrivateDetails = {}; this.familyDetails = {}; this.wenath = {}; } } module.exports = Users;
2. 修改控制器逻辑,显式查询子集合数据
Firestore获取文档时不会自动拉取子集合,必须显式查询每个子集合。同时注意用for...of替代forEach处理异步操作,确保所有数据都获取完成后再返回:
'use strict'; const firebase = require('../db'); const Users = require('../models/users'); const firestore = firebase.firestore(); const getAllUsers = async (req, res, next) => { try { const usersCollection = firestore.collection('users'); const usersSnapshot = await usersCollection.get(); const userArray = []; if (usersSnapshot.empty) { return res.status(404).send('未找到用户数据'); } // 用for...of处理异步查询,forEach无法正确等待async函数执行完成 for (const doc of usersSnapshot.docs) { const userData = doc.data(); // 创建用户实例 const user = new Users( doc.id, userData.name, userData.email, userData.provider, userData.firstWord, userData.leda, userData.age, userData.birthday, userData.district, userData.gender, userData.familyChildren, userData.fatherEducation, userData.monthlyIncome, userData.motherEducation, userData.whichChild, userData.awaSE, userData.awaUN, userData.kathakaraaSE, userData.kathakaraaUN ); // 查询并赋值子集合数据(假设每个子集合只有一个文档,若有多文档需遍历docs数组) const childGrowSnapshot = await doc.ref.collection('childGrow').get(); if (!childGrowSnapshot.empty) { user.childGrow = childGrowSnapshot.docs[0].data(); } const childPrivateDetailsSnapshot = await doc.ref.collection('childPrivateDetails').get(); if (!childPrivateDetailsSnapshot.empty) { user.childPrivateDetails = childPrivateDetailsSnapshot.docs[0].data(); } const familyDetailsSnapshot = await doc.ref.collection('familyDetails').get(); if (!familyDetailsSnapshot.empty) { user.familyDetails = familyDetailsSnapshot.docs[0].data(); } const wenathSnapshot = await doc.ref.collection('wenath').get(); if (!wenathSnapshot.empty) { user.wenath = wenathSnapshot.docs[0].data(); } userArray.push(user); } res.send(userArray); } catch (error) { res.status(400).send(error.message); } } module.exports = { getAllUsers };
关键说明
- Firestore的
get()方法仅返回当前集合的文档数据,不会自动包含子集合,必须显式调用doc.ref.collection(子集合名).get()查询。 - 用
for...of替代forEach是因为forEach无法正确等待内部的异步查询完成,会导致部分子集合数据未被获取就返回结果。 - 若子集合包含多个文档,需修改子集合数据的处理逻辑,将结果整理为数组而非单个对象。
内容的提问来源于stack exchange,提问作者Dasun Dola
相关产品推荐
相关产品推荐

