如何在Mongoose中查询父子引用评论,将回复ID转为数组返回?
两种实现方案:虚拟属性 & 聚合框架
一、用虚拟属性实现
直接在你的Schema中定义虚拟属性,反向关联所有回复当前评论的子评论ID:
const commentSchema = new Schema( { content: String, score: Number, replyingTo: { type: mongoose.Types.ObjectId, ref: "Comment" }, }, // 开启虚拟属性的序列化支持,否则查询结果里不会显示 { toJSON: { virtuals: true }, toObject: { virtuals: true } } ); // 定义replies虚拟属性,获取所有以当前评论为父级的子评论ID commentSchema.virtual('replies', { ref: 'Comment', localField: '_id', // 当前评论的ID foreignField: 'replyingTo', // 子评论中指向父级的字段 justOne: false, // 返回数组而非单个文档 // 转换结果,只保留子评论的ID transform: (docs) => docs.map(doc => doc._id.toString()) }); const Comment = mongoose.model("Comment", commentSchema);
查询时需要通过populate加载虚拟属性:
// 查询单个评论并加载其回复ID数组 const targetComment = await Comment.findById(yourCommentId).populate('replies'); // 此时targetComment.replies就是你需要的ID数组
二、用聚合框架实现
如果不想修改Schema,可以直接通过聚合管道在查询时生成目标格式:
const formattedComments = await Comment.aggregate([ // 关联所有回复当前评论的子评论 { $lookup: { from: 'comments', // 注意:mongoose默认集合名为模型名的小写复数 localField: '_id', foreignField: 'replyingTo', as: 'replies' } }, // 将关联结果转换为仅包含ID的数组 { $project: { content: 1, score: 1, replies: { $map: { input: '$replies', as: 'item', in: '$$item._id' } } } } ]);
执行后返回的formattedComments数组中,每个对象都会包含replies字段,格式完全符合你的需求。
内容的提问来源于stack exchange,提问作者sasan
相关产品推荐
相关产品推荐

