2

我有一个像这样的视频架构:

const VideoSchema = new mongoose.Schema({
  caption: {
    type: String,
    trim: true,
    maxlength: 512,
    required: true,
  },
  owner: {
    type: mongoose.Schema.ObjectId,
    ref: 'User',
    required: true,
  },
  // some more fields
  comments: [{
    type: mongoose.Schema.ObjectId,
    ref: 'Comment',
  }],
  commentsCount: {
    type: Number,
    required: true,
    default: 0,
  },
}, { timestamps: true });

和一个像这样的简单评论模式:

const CommentSchema = new mongoose.Schema({
  text: {
    type: String,
    required: true,
    maxLength: 512,
  },
  owner: {
    type: mongoose.Schema.ObjectId,
    ref: 'User',
    required: true,
  },
  videoId: {
    type: mongoose.Schema.ObjectId,
    ref: 'Video',
    required: true,
    index: true,
  },
}, { timestamps: true });

使用这样的模式,我可以对我的 Video 集合执行任何类型的查找查询,并用它的评论填充它:

Video.find({ owner: someUserId }).populate({ path: 'comments' });

我的问题是在视频集合中保留评论 ID 有多大必要?鉴于我已经在我的 Comment 模式中索引了 videoId 字段,那么摆脱这些评论 id 和它们的数量并使用聚合 $lookup 来查找视频的评论会有多糟糕(谈到性能),如下所示:

Video.aggregate([
  {
    $match: {
      owner: someUserId,
    },
  },
  {
    $lookup: {
      from: 'comments',
      localField: '_id',
      foreignField: 'videoId',
      as: 'comments',
    }
  }
])

这些在性能方面有何不同?

4

1 回答 1

3

好吧,没有办法$lookup比在实际视频对象上拥有评论 ID 列表更快。我的意思是你现在必须做一个whole other requestto mongo 才能得到它们。所以性能方面显然查找会增加时间。那是假设您不使用mongoose populate将这些评论 ID“转换”为引用的对象。

如果您要从视频中删除评论(以及实际的计数道具)并进行查找是要走的路。由于您立即在您的 arg 中进行匹配,然后做一个简单的lookup操作,我看不出这对您来说是个瓶颈。您还可以优化/更改/调整您的聚合 vie解释等。

你的视频模式会很干净:

const VideoSchema = new mongoose.Schema({
  caption: {
    type: String,
    trim: true,
    maxlength: 512,
    required: true,
  },
  owner: {
    type: mongoose.Schema.ObjectId,
    ref: 'User',
    required: true,
  },
  // some more fields
}, { timestamps: true });
于 2019-06-12T07:22:56.880 回答