Mongoose .populate() 或 .find() 哪个更快

问题描述

我想获取用户相关的帖子。哪个更快

  • 查找用户并填充帖子

    User.findOne({ _id: id}).populate("posts")

  • 或者直接在帖子模型中搜索

    Post.find({ owner: user_id })

解决方法

此基准代码表明 Post.find({ owner: user_id }) 的速度要快一些。

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const NUM_USERS = 100;
const NUM_POSTS_PER_USER = 10;

mongoose.connect('mongodb://localhost:27017/testdb',{ useNewUrlParser: true });

const userSchema = Schema({
  posts: [{ type: Schema.Types.ObjectId,ref: 'Post' }]
});

const postSchema = Schema({
  owner: { type: Schema.Types.ObjectId,ref: 'User' },title: String,content: String,});

const User = mongoose.model('User',userSchema);
const Post = mongoose.model('Post',postSchema);

const userIds = [];

async function seed() {
  await User.deleteMany({});
  await Post.deleteMany({});

  for (let i = 0; i < NUM_USERS; ++i) {
    const user = new User();
    await user.save();

    for (let i = 0; i < NUM_POSTS_PER_USER; ++i) {
      const post = new Post({
        owner: user,title: Array(50).fill('a').join(''),content: Array(1000).fill('b').join(''),});

      await post.save();

      user.posts.push(post);
    }

    await user.save();
    userIds.push(user._id);
  }
}

async function benchmarkPopulate() {
  console.time('populate');

  for (const id of userIds) {
    await User.findOne({ _id: id }).populate("posts");
  }

  console.timeEnd('populate');
}

async function benchmarkFind() {
  console.time('find');

  for (const user_id of userIds) {
    await Post.find({ owner: user_id });
  }

  console.timeEnd('find');
}

async function main() {
  await seed();
  await benchmarkPopulate();
  await benchmarkFind();
  await benchmarkPopulate();
  await benchmarkFind();
  await mongoose.disconnect();
}

main();

输出:

populate: 217.534ms
find: 121.905ms
populate: 169.181ms
find: 120.171ms

这并不奇怪,因为 Post.find({ owner: user_id }) 只需要查询一个集合。

这些结果在各次运行中相当一致(即使您颠倒了基准测试的顺序)。

您的里程可能会有所不同,这种差异并不重要,尤其是当您通过网络查询数据库时。