mongodb汇总$ lookup vs查找并填充

时间:2019-06-11 08:19:53

标签: node.js mongodb mongoose aggregation-framework

我有一个像这样的视频模式:

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 });

和一个简单的Comment模式:

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.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',
    }
  }
])

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

1 个答案:

答案 0 :(得分:0)

$lookup不可能比在实际视频对象上具有评论ID的列表更快。我的意思是,您必须对whole other request做mongo才能立即获得它们。因此,从性能角度来看,显然查找会增加时间。假设您没有使用mongoose populate将这些注释ID“转换”为引用的对象。

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

您的视频架构将非常干净:

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 });