如何检查userId是否已存在于Mongoose的ObjectId数组likes中?
解决Mongoose数组中检查用户点赞状态的问题
你遇到的问题是因为调用populate('likes')后,postToUpdate.likes变成了User文档对象的数组,而非数据库中存储的ObjectId数组,直接用includes比较字符串/ObjectId和对象自然不生效。下面提供几种可行的解决方案:
方案1:不使用populate,直接检查ObjectId数组(推荐,更高效)
不需要关联查询用户信息的话,直接操作数据库存储的ObjectId数组即可:
const postId = req.params.id; const userId = req.body.userId; const postToUpdate = await Posts.findById(postId); // 方法1:用原生数组some方法,转字符串避免ObjectId类型差异 const hasLiked = postToUpdate.likes.some(id => id.toString() === userId.toString()); // 方法2:用Mongoose数组自带的includes方法(支持ObjectId与字符串的比较) // const hasLiked = postToUpdate.likes.includes(userId); if (!hasLiked) { postToUpdate.likes.push(userId); await postToUpdate.save(); }
方案2:已populate时,遍历对象数组比较_id
如果必须获取用户信息而使用了populate,需要遍历数组中的User对象,比较其_id字段:
const postId = req.params.id; const userId = req.body.userId; const postToUpdate = await Posts.findById(postId).populate('likes'); const hasLiked = postToUpdate.likes.some(user => user._id.toString() === userId.toString()); if (!hasLiked) { postToUpdate.likes.push(userId); await postToUpdate.save(); }
方案3:数据库层面直接判断并更新(性能最优)
通过数据库查询直接判断点赞状态,无需取出整个文档,适合高并发场景:
const postId = req.params.id; const userId = req.body.userId; // 检查是否已点赞 const hasLiked = await Posts.findOne({ _id: postId, likes: userId }); if (!hasLiked) { // 直接更新数组 await Posts.findByIdAndUpdate(postId, { $push: { likes: userId } }); }
内容的提问来源于stack exchange,提问作者Enrico
相关产品推荐
相关产品推荐

