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

Mongoose查询时排除依赖字段后如何获取virtual虚拟属性值

你之前使用的虚拟属性是客户端计算逻辑,必须依赖完整的likes数组返回才能计算,既然你查询时排除了likes字段,文档内没有对应数据,虚拟属性自然无法正常生成点赞数。你可以选择以下两种方案解决问题:

方案1:使用MongoDB聚合管道在数据库侧直接计算点赞数

用$size聚合操作符可以直接在数据库层面统计likes数组的长度,不需要把整个数组返回给服务端,性能开销极低:

const post = await Post.aggregate([
  // 匹配指定ID的帖子
  { $match: { _id: mongoose.Types.ObjectId(postId) } },
  // 新增numLikes字段,值为likes数组的长度
  { $addFields: { numLikes: { $size: "$likes" } } },
  // 排除不需要返回的字段
  { $project: { likes: 0, shares: 0 } }
])
// 聚合返回的是数组,取第一个元素即为目标帖子
const targetPost = post[0]
方案2:新增持久化的点赞数字段(高并发场景更推荐)

如果点赞数是高频查询的属性,建议直接在Schema中新增numLikes普通字段存储点赞数,每次点赞/取消点赞操作时原子更新该字段,后续查询直接返回字段值即可,不需要额外计算:

  1. 首先修改Schema定义:
const postSchema = new mongoose.Schema({
  UserId: mongoose.Types.ObjectId,
  Title: String,
  Desc: String,
  likes: [mongoose.Types.ObjectId],
  shares: [mongoose.Types.ObjectId],
  // 新增持久化点赞数字段,默认值0
  numLikes: { type: Number, default: 0 }
})
  1. 点赞/取消点赞操作的原子更新示例:
// 点赞:同时给numLikes加1,把用户ID加入likes数组(原子操作避免数据不一致)
await Post.findByIdAndUpdate(postId, {
  $inc: { numLikes: 1 },
  $push: { likes: userId }
})

// 取消点赞:同时给numLikes减1,把用户ID从likes数组移除
await Post.findByIdAndUpdate(postId, {
  $inc: { numLikes: -1 },
  $pull: { likes: userId }
})
  1. 后续查询直接正常取字段即可,不需要额外处理:
const post = await Post.findById(postId).select("-likes -shares")
// 直接获取点赞数
console.log(post.numLikes)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 10:21:03