如何修复Mongoose中Cannot read properties of null (reading 'populated')错误?
Mongoose嵌套Populate报错:Cannot read properties of null (reading 'populated')
我使用Mongoose和Node.js处理订单数据,需要对订单中的products字段做嵌套关联填充,但测试时部分数据正常运行,部分数据抛出如下错误。
代码示例
订单Schema(orderSchema)
const { ObjectId } = mongoose.Schema.Types; const orderSchema = new mongoose.Schema({ name: { type: String, required: false }, products: [ { product: { type: ObjectId, ref: 'products', required: false }, quantity: { type: Number, required: false, default: 0 }, unit: { type: String, required: false, default: '' } } ] }, { timestamps: true }); const orderModel = mongoose.model('orders', orderSchema);
产品Schema(productSchema)
const productSchema = new mongoose.Schema( { name: { type: String, required: true }, type: { type: String, required: true } }, { timestamps: true }); const productModel = mongoose.model('products', productSchema);
关联填充查询代码
const result = await orderModel.find({}).populate({ path: 'products', model: 'products', select: { quantity: 1, unit: 1, product: 1 }, populate: { path: 'product', model: 'products', select: { type: 1, name: 1 } } }); console.log('result', result);
数据库中的订单数据
[ { "_id": { "$oid": "64e8b34b24bf0243bc87fa82" }, "name": "ORDER 1", "products": [ { "quantity": 100, "unit": "kg", "_id": { "$oid": "64e8d05a1be39f48906dec4b" }, "product": { "$oid": "64e8b34724bf0243bc87fa2f" } } ], "createdAt": { "$date": { "$numberLong": "1692971851401" } }, "updatedAt": { "$date": { "$numberLong": "1692979290410" } }, "__v": 0 } ]
错误信息
Cannot read properties of null (reading 'populated')
错误堆栈:
TypeError: Cannot read properties of null (reading 'populated') at markArraySubdocsPopulated (C:\Users\user\OneDrive\Documents\backend\backendNodeJS - Copie\node_modules\mongoose\lib\helpers\populate\markArraySubdocsPopulated.js:41:18) at assignVals (C:\Users\user\OneDrive\Documents\backend\backendNodeJS - Copie\node_modules\mongoose\lib\helpers\populate\assignVals.js:195:7) at _assign (C:\Users\user\OneDrive\Documents\backend\backendNodeJS - Copie\node_modules\mongoose\lib\model.js:5119:3) at _done (C:\Users\user\OneDrive\Documents\backend\backendNodeJS - Copie\node_modules\mongoose\lib\model.js:4931:9) at _next (C:\Users\user\OneDrive\Documents\backend\backendNodeJS - Copie\node_modules\mongoose\lib\model.js:4919:7) at C:\Users\user\OneDrive\Documents\backend\backendNodeJS - Copie\node_modules\mongoose\lib\model.js:5028:5 at C:\Users\user\OneDrive\Documents\backend\backendNodeJS - Copie\node_modules\mongoose\lib\model.js:5353:18 at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
问题原因与解决方案
问题根源
第一层populate中错误指定了model: 'products',但products是订单文档的子文档数组,并非引用products模型的字段。Mongoose无法找到对应关联,处理空值或无效引用时触发报错。部分数据正常是因为这些订单的products.product引用的产品文档存在,而报错数据可能存在无效引用或空值。
修复后的查询代码
去掉第一层populate的model配置,直接填充子文档内的product字段:
// 简化写法,直接指定嵌套路径 const result = await orderModel.find({}).populate({ path: 'products.product', select: 'type name' }); console.log('result', result);
如果需要保留子文档的quantity、unit字段,可使用正确的嵌套populate写法:
const result = await orderModel.find({}) .populate({ path: 'products', select: 'quantity unit product', populate: { path: 'product', model: 'products', select: 'type name' } }); console.log('result', result);
额外优化建议
- 检查数据库中订单的
products.product字段,清理引用不存在产品ID的数据,或添加match过滤有效引用:
populate: { path: 'product', model: 'products', select: 'type name', match: { _id: { $exists: true } } }
- 确保代码中正确导入
ObjectId类型,避免类型不匹配问题。
内容的提问来源于stack exchange,提问作者Dev M
相关产品推荐
相关产品推荐

