Skip to content

Virtual Populate and perDocumentLimit not working as documented? #9418

@qqilihq

Description

@qqilihq

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
We use a virtual populate, and want to ensure, that each of the properties is populated (if available) with one document. Following the FAQ, we set the perDocumentLimit to one. When running the query, Mongoose does not execute a separate query as described in the FAQ and thus documents are missing.

If the current behavior is a bug, please provide the steps to reproduce.

import mongoose from 'mongoose';

beforeAll(async () => mongoose.connect(process.env.MONGO_URL as string));

afterAll(async () => mongoose.disconnect());

// mongoose.set('debug', true);

it('Mongoose virtual populate', async () => {
  const schema1 = new mongoose.Schema(
    {
      // nothing here
    },
    {
      toJSON: {
        virtuals: true
      }
    }
  );

  schema1.virtual('model2', {
    ref: 'schema2',
    localField: '_id',
    foreignField: 'schema1id'
  });

  const schema2 = new mongoose.Schema({
    schema1id: { type: mongoose.Types.ObjectId, ref: 'schema1' }
  });

  const Model1 = mongoose.model<any>('schema1', schema1);
  const Model2 = mongoose.model<any>('schema2', schema2);

  const m1doc1 = await Model1.create({});
  const m1doc2 = await Model1.create({});

  await Model2.create({ schema1id: m1doc1._id });
  const m2doc1 = await Model2.create({ schema1id: m1doc1._id });
  const m2doc2 = await Model2.create({ schema1id: m1doc2._id });

  const result = await Model1.find({})
    .populate({ path: 'model2', options: { perDocumentLimit: 1, sort: { _id: -1 } } })
    .exec();

  expect(result).toBeArrayOfSize(2);
  expect(result[0].model2).toBeArray();
  expect(result[1].model2).toBeArray();
  expect(result[0].model2[0]._id).toEqual(m2doc1._id);
  expect(result[1].model2[0]._id).toEqual(m2doc2._id);
});

Here’s the query log:

Mongoose: schema1.find({}, { projection: {} })
Mongoose: schema2.find({ schema1id: { '$in': [ ObjectId("5f5f72d7ce68e219cf102da7"), ObjectId("5f5f72d7ce68e219cf102da8") ] }}, { skip: undefined, limit: 1, sort: { _id: -1 }, projection: {} })

What is the expected behavior?
Test should pass. Each returned result item should have a model2 array with one item.

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that "latest" is not a version.
Mongoose 5.10.5
Node v12.1.0
MongoDB 4.2.8

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugWe've confirmed this is a bug in Mongoose and will fix it.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions