Prerequisites
Mongoose version
6.6.5, tested also with 7.3.1
Node.js version
16.19.1
MongoDB server version
5.0.17
Typescript version (if applicable)
No response
Description
When using .populate during a .find query with .cursor().eachAsync on a relation array (field: [{ type: Schema.Types.ObjectId, ref: 'MyModel' }]), all .push calls (and possibly other array methods) fail with Model is not a costructor seemingly because the populated field is not correctly marked as populated.
Steps to Reproduce
Create a new npm/yarn folder, install mongoose and run following script:
const mongoose = require("mongoose");
const { Schema } = mongoose;
const Company = mongoose.model(
"Company",
new Schema({ name: String }),
"companies"
);
const User = mongoose.model(
"User",
new Schema({
name: String,
companies: [{ type: Schema.Types.ObjectId, ref: "Company" }],
}),
"users"
);
const main = async () => {
await mongoose.connect(
"mongodb://localhost:27017/populate-push-crash-testing"
);
await Company.insertMany([{ name: "Company 1" }, { name: "Company 2" }]);
const company = await Company.findOne({ name: "Company 1" });
const company2 = await Company.findOne({ name: "Company 2" });
await User.insertMany([{ name: "User 1", companies: [company.id] }]);
await User.find()
.populate("companies")
.cursor()
.eachAsync(async (user) => {
if (!user.populated("companies")) await user.populate("companies");
user.companies.push(company2);
await user.save();
});
};
main()
.catch(console.error)
.finally(() => {
process.exit(0);
});
It will produce following error:
TypeError: Model is not a constructor
at Proxy._cast (PROJECT-PATH/node_modules/mongoose/lib/types/array/methods/index.js:242:17)
at Proxy._mapCast (PROJECT-PATH/node_modules/mongoose/lib/types/array/methods/index.js:260:17)
at Arguments.map (<anonymous>)
at Proxy.push (PROJECT-PATH/node_modules/mongoose/lib/types/array/methods/index.js:683:21)
at PROJECT-PATH/index.js:36:22
at handleNextResult (PROJECT-PATH/node_modules/mongoose/lib/helpers/cursor/eachAsync.js:173:22)
at PROJECT-PATH/node_modules/mongoose/lib/helpers/cursor/eachAsync.js:164:11
at PROJECT-PATH/node_modules/mongoose/lib/cursor/QueryCursor.js:552:7
at PROJECT-PATH/node_modules/kareem/index.js:191:16
at processTicksAndRejections (node:internal/process/task_queues:78:11)
However if you remove the .populate call in the .find query, everything seems to work fine. The example is simplified, in our real case we call a method on the model and want to be sure the field is populated, for now I've added a depopulate call and a populate call after that, which makes it work.
Another interesting thing is if I remove the cursor and simply do:
for (const user of await User.find().populate("companies")) {
if (!user.populated("companies")) await user.populate("companies");
user.companies.push(company2);
await user.save();
}
It also seems to work, so this error might be related to cursor?
Expected Behavior
There should be no Error, mongoose should correctly mark the field as populated and the push should work.
Prerequisites
Mongoose version
6.6.5, tested also with 7.3.1
Node.js version
16.19.1
MongoDB server version
5.0.17
Typescript version (if applicable)
No response
Description
When using
.populateduring a.findquery with.cursor().eachAsyncon a relation array (field: [{ type: Schema.Types.ObjectId, ref: 'MyModel' }]), all .push calls (and possibly other array methods) fail withModel is not a costructorseemingly because the populated field is not correctly marked as populated.Steps to Reproduce
Create a new npm/yarn folder, install mongoose and run following script:
It will produce following error:
However if you remove the
.populatecall in the.findquery, everything seems to work fine. The example is simplified, in our real case we call a method on the model and want to be sure the field is populated, for now I've added a depopulate call and a populate call after that, which makes it work.Another interesting thing is if I remove the cursor and simply do:
It also seems to work, so this error might be related to cursor?
Expected Behavior
There should be no Error, mongoose should correctly mark the field as populated and the push should work.