Do you want to request a feature or report a bug?
Report a bug.
What is the current behavior?
Now, when we use .lean()
on a query, and populate on the same query, the main document is converted to a POJO, while the subdocs aren't.
What is the expected behavior?
.lean()
should convert the document, and all subdocuments to POJO.
quoting @vkarpov15 on https://github.com/Automattic/mongoose/issues/4802#issuecomment-267864633
Just do .lean() on the query if you want to use lean and that'll make the top level doc and every subdoc lean.
also, I have other suggestions according to lean that can be sum up in:
The lean option precedence should be like this:
1- Is it set explicitly? Then use it.
2- not explicitly? find the closest parent that has a lean option set in, and take that as the setting.
The closest thing I can think of to this is css inheritance, I hope it's clear what I mean, let me know if I can elaborate more in any way.
If this behavior is accepted, let me know and I can work on it in a week or so.
repro script:
nodemon --exec mocha test.js -R min
// test.js
const mongoose = require('mongoose');
const { Schema } = mongoose;
const assert = require('assert');
mongoose.connect('mongodb://localhost:27017/test');
const userSchema = new Schema({
name: String,
roomId: { type: Schema.ObjectId, ref: 'Room' }
});
const officeSchema = new Schema();
const roomSchema = new Schema({ officeId: { type: Schema.ObjectId, ref: 'Office' } });
const User = mongoose.model('User', userSchema);
const Office = mongoose.model('Office', officeSchema);
const Room = mongoose.model('Room', roomSchema);
const user = new User();
const office = new Office();
const room = new Room();
user.roomId = room._id;
room.officeId = office._id;
const isLean = (doc) => !(doc instanceof mongoose.Document);
describe('lean', function () {
this.timeout(10000);
before(async () => {
await Promise.all([User.remove(), Office.remove(), room.remove()]);
await Promise.all([user.save(), office.save(), room.save()]);
});
it('document, and subdocuments are not lean by default', async () => {
let user = await User.findOne()
.populate({
path: 'roomId',
populate: {
path: 'officeId'
}
});
assert.equal(isLean(user), false);
assert.equal(isLean(user.roomId), false);
assert.equal(isLean(user.roomId.officeId), false);
});
describe('lean inheritance', () => {
it('.lean() makes query result, and all populated fields lean', async () => {
let user = await User.findOne()
.populate({
path: 'roomId',
populate: {
path: 'officeId'
}
})
.lean();
assert.equal(isLean(user), true);
assert.equal(isLean(user.roomId), true);
assert.equal(isLean(user.roomId.officeId), true);
});
it('disabling lean at some populating level reflects on it, and descendants', async () => {
let user = await User.findOne()
.populate({
path: 'roomId',
options: { lean: false },
populate: {
path: 'officeId'
}
})
.lean();
assert.equal(isLean(user), true);
assert.equal(isLean(user.roomId), false);
assert.equal(isLean(user.roomId.officeId), false);
});
it('enabling lean at some populating level reflects on it, and descendants', async () => {
let user = await User.findOne()
.populate({
path: 'roomId',
options: { lean: true },
populate: {
path: 'officeId'
}
});
assert.equal(isLean(user), false);
assert.equal(isLean(user.roomId), true);
assert.equal(isLean(user.roomId.officeId), true);
});
it('disabling lean on nested population overwrites parent lean', async () => {
let user = await User.findOne()
.populate({
path: 'roomId',
options: { lean: true },
populate: {
options: { lean: false },
path: 'officeId'
}
});
assert.equal(isLean(user), false);
assert.equal(isLean(user.roomId), true);
assert.equal(isLean(user.roomId.officeId), false);
});
});
});
Node v10.1.0
MongoDB v3.2.7
Mongoose v5.1.2
Thanks for reporting, will investigate asap :+1:
Thank you for reporting and the quick fix.
was going to report this myself instead just ran npm update..! 馃憤 馃檪
Most helpful comment
Thank you for reporting and the quick fix.
was going to report this myself instead just ran npm update..! 馃憤 馃檪