社交媒体后端: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
相关产品推荐
相关产品推荐

