14

I've noticed that .populate function in mongoose 4.7.3 runs separate queries on the database for each lookup:

  db.House
    .populate('ownerId')
    .exec((err, result) => {
    ..

With aggregation pipeline we can lookup multiple collections with a single query:

    db.House.aggregate([
    {
      $lookup:
      {
        from: 'owners',
        localField: 'ownerId',
        foreignField: '_id',
        as: 'owner',
      },

What is the reason for mongoose to do separate queries with .populate? Is the aggregation function more performant on lookups?

F.H.
  • 1,456
  • 1
  • 20
  • 34
  • 3
    The `populate()` functionality in Mongoose is a client-side query aggregation feature that predates the addition of server-side `$lookup` support in MongoDB 3.2. – Stennie Apr 08 '19 at 23:30

1 Answers1

24

Here's a summary of the differences:

$lookup

  • can only be used with aggregate
  • can only be used to pull in referenced documents from unsharded collections
  • can pull in referenced documents by any field
  • generally more performant as it's a server-side operation
  • requires MongoDB 3.2+

Mongoose populate()

  • can be used with find and aggregate
  • can be used to to pull in referenced documents from both sharded and unsharded collections
  • can only pull in referenced documents by _id
  • no MongoDB version requirement
JohnnyHK
  • 305,182
  • 66
  • 621
  • 471
  • I'm wondering... did I read the [mongoddb manual](https://docs.mongodb.com/manual/core/aggregation-pipeline-sharded-collections/) wrong? I found information that aggregate works on sharded dbs as well. – Adrian Moisa Feb 18 '20 at 14:10
  • 3
    @AdrianMoisa `aggregate` can, but not `$lookup`. I added a link to the docs for that. – JohnnyHK Feb 18 '20 at 14:27
  • Thank you for the clarification. Just found this interesting [answer](https://stackoverflow.com/questions/34633111/mongodb-to-use-sharding-with-lookup-aggregation-operator). Same point as you made. – Adrian Moisa Feb 18 '20 at 18:37
  • Can I not .populate() by something other than _id? I thought you could set a virtual on your schema by providing a localField and foreignField (with ref to model) and .populate(). I guess I never tried, but I would imagine I could just set localField or foreignField to something other than "_id"? – Ticdoc Mar 06 '20 at 19:31