Express中Mongoose查询Tweet时populate likes返回空数组问题
问题:查询Tweet时populate likes字段返回空数组
问题详情
我定义了如下两个Mongoose Schema:
Like模型Schema
//create likes schema const likes = mongoose.Schema({ liked: { type: Boolean, default: false }, tweet: { type: Schema.Types.ObjectId, ref: "Tweet" }, author: { type: Schema.Types.ObjectId, ref: "User" } }); module.exports = mongoose.model('Like', likes);
Tweet模型Schema
const tweets = mongoose.Schema({ content: { type: String, required: true, }, author: { type: Schema.Types.ObjectId, ref: "User" }, likes: [{ type: Schema.Types.ObjectId, ref: "Like" }] }); module.exports = mongoose.model('Tweet', tweets);
测试Like的populate查询时结果正常:
const likes = await Like.find().populate("author", "_id name email").populate("tweet", "_id content").exec() res.json(likes)
返回数据:
[ { "_id": "63921e53deb31c60249901e4", "liked": true, "tweet": { "_id": "63921e50deb31c60249901e1", "content": "tweet 1" }, "author": { "_id": "63921e2ddeb31c60249901dd", "name": "Dave", "email": "something@gmail.com" }, "createdAt": "2022-12-08T17:26:43.650Z", "updatedAt": "2022-12-08T17:26:43.650Z", "__v": 0 } ]
但查询Tweet并populate likes字段时,得到的likes数组为空:
const tweets = await Tweet.find() .populate("author", "_id name email") .populate("likes", "_id") .sort({updatedAt: "desc"}) .exec() res.status(200).json(tweets)
返回数据:
[ { "_id": "6393701aa62997f3454e81e1", "content": "My tweet", "author": "63936ffaa62997f3454e81dd", "likes": [], "createdAt": "2022-12-09T17:27:54.146Z", "updatedAt": "2022-12-09T17:27:54.146Z", "__v": 0 } ]
实际Like集合中存在对应该Tweet的记录:
[ { "_id": "63937140df6222756bd84ede", "liked": true, "tweet": { "_id": "6393701aa62997f3454e81e1", "content": "My tweet" }, "author": { "_id": "63936ffaa62997f3454e81dd", "name": "Dave", "email": "admin@gmail.com" }, "createdAt": "2022-12-09T17:32:48.251Z", "updatedAt": "2022-12-09T17:32:48.251Z", "__v": 0 } ]
解决方案
问题核心是双向引用未同步更新:Mongoose不会自动维护跨文档的双向关联,你创建Like记录时仅在Like文档中关联了Tweet ID,但未将Like ID同步添加到对应Tweet的likes数组中,导致populate时无法匹配到关联数据。
修复步骤:
创建Like时同步更新Tweet
新增Like记录后,手动更新对应Tweet的likes数组:// 创建Like示例 const newLike = new Like({ liked: true, tweet: tweetId, // 目标Tweet的ID author: userId }); await newLike.save(); // 同步更新Tweet的likes数组 await Tweet.findByIdAndUpdate( tweetId, { $push: { likes: newLike._id } }, { new: true } // 返回更新后的文档 );补全已有数据的关联
针对已存在的Like记录,批量同步到对应Tweet:const allLikes = await Like.find().populate('tweet'); for (const like of allLikes) { if (like.tweet && !like.tweet.likes.includes(like._id)) { await Tweet.findByIdAndUpdate( like.tweet._id, { $push: { likes: like._id } } ); } }可选:用中间件自动维护关联
给Like模型添加post中间件,自动处理关联更新,避免手动操作:// 保存Like后同步更新Tweet likes.post('save', async function(doc) { await Tweet.findByIdAndUpdate( doc.tweet, { $addToSet: { likes: doc._id } }, // $addToSet避免重复添加 { new: true } ); }); // 删除Like时从Tweet中移除关联 likes.post('remove', async function(doc) { await Tweet.findByIdAndUpdate( doc.tweet, { $pull: { likes: doc._id } }, { new: true } ); });
完成以上操作后,重新执行Tweet的populate查询,即可正确获取到关联的Like记录。
内容的提问来源于stack exchange,提问作者WaqasRaza
相关产品推荐
相关产品推荐

