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

社交媒体后端:Mongoose异步查询结果无法正确返回问题求助

获取用户关联帖子返回空对象数组的问题解决

问题背景

我开发社交媒体后端时,将用户数据存在User模型,帖子存在Post模型,User通过Schema.Types.ObjectId关联Post模型。现在通过向/post路由发送GET请求(请求体携带用户ID),尝试获取该用户的所有帖子,但返回的是与实际帖子数量一致的空对象数组。

请求体示例

{ "id" : "6399d54c00308a2fe0bdf9fc"}

出现问题的代码

const getPost = async(req, res)=>{
    if(req.body.id){
        try {
            const user = await User.findById(req.body.id).select('-_id post');
            // 问题出在这里
            const posts = await user.post.map(async(postID) => {
                const result = await Post.findById(postID).select('-_id title body');
                // console.log(result) 能正确打印数据库中的对象
                return result; // 此处返回空对象
            });
            res.status(200).json(posts);
        } catch (error) {
            console.log(error);
            res.status(500).json({message: error.message});
        }
    }
};

响应结果

[{},{},{},{},{},{},{},{},{},{},{}]

用户对象示例

{
  "_id": "6399d54c00308a2fe0bdf9fc",
  "createdAt": "2022-12-14T13:52:40.483Z",
  "name": "ShivamUttam",
  "username": "Fadedrifleman",
  "post": [
    "6399d57200308a2fe0bdfa00",
    "6399d5c400308a2fe0bdfa06",
    "6399d5ca00308a2fe0bdfa0a",
    "6399d5d600308a2fe0bdfa0e",
    "6399de29e8aa8697299941c5",
    "6399dec6e9b79ac66c59cd7a",
    "6399df0dbea937f8b3365979",
    "6399df31bea937f8b336597d",
    "6399df31bea937f8b3365981",
    "6399df32bea937f8b3365985",
    "6399df33bea937f8b3365989"
  ],
  "__v": 5
}

User模型

const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
    createdAt: {
        type: Date,
        default: Date.now()
    },
    name: {
        type: String,
        required: [true, 'name must be provided'],
    },
    username : {
        type: String,
        required: [true, 'Username must be provided'],
    },
    post:[{
        type: mongoose.Schema.Types.ObjectId,
         ref: 'Post',
    }],
});
module.exports = mongoose.model('User', userSchema)

Post模型

const mongoose = require('mongoose')
const postSchema = new mongoose.Schema({
    createdAt: {
        type: Date,
        default: Date.now()
    },
    title:{
        type: String,
        required: [true, "title cannot be empty"],
        max: [20, "title cannot exceed 20 character"]
    },
    body: {
        type: String,
        max: [145, "body cannot exceed 145 character"],
    },
    tags:{
        type: String,
    },
});
module.exports = mongoose.model('Post', postSchema);

问题原因

Array.map()中使用async函数时,返回的是一个Promise数组,而非实际的查询结果。直接await这个数组不会等待所有Promise完成,最终posts是未resolved的Promise集合,JSON序列化后就会变成空对象。

解决方案

方案一:使用Promise.all等待所有Promise完成

修改循环查询的代码,用Promise.all()包裹map返回的Promise数组,确保所有查询都完成后再返回结果:

const getPost = async(req, res)=>{
    if(req.body.id){
        try {
            const user = await User.findById(req.body.id).select('-_id post');
            // 用Promise.all处理所有异步查询
            const posts = await Promise.all(user.post.map(async(postID) => {
                return await Post.findById(postID).select('-_id title body');
            }));
            res.status(200).json(posts);
        } catch (error) {
            console.log(error);
            res.status(500).json({message: error.message});
        }
    }
};

方案二:使用Mongoose的populate直接关联查询(推荐)

利用Mongoose的populate功能,直接在查询用户时关联查询对应的帖子,避免多次数据库请求(解决N+1查询问题):

const getPost = async(req, res)=>{
    if(req.body.id){
        try {
            // 查询用户并直接填充post字段的内容
            const user = await User.findById(req.body.id)
                .select('-_id post')
                .populate({
                    path: 'post',
                    select: '-_id title body' // 指定只返回title和body字段
                });
            res.status(200).json(user.post);
        } catch (error) {
            console.log(error);
            res.status(500).json({message: error.message});
        }
    }
};

这个方案更高效,只需要一次数据库操作就能获取用户及其关联的帖子数据,性能优于循环查询。

内容的提问来源于stack exchange,提问作者user18847228

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 05:20:22