You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 22:15:27