Mongoose populate with array of objects containing ref
JavascriptMongooseJavascript Problem Overview
I have a Mongoose schema with an array lists
of objects that consist of a reference to another collection and a nested array of numbers:
var Schema, exports, mongoose, schema;
mongoose = require("mongoose");
Schema = mongoose.Schema;
schema = new Schema({
name: {
type: String,
required: true,
unique: true,
trim: true
},
lists: [
{
list: {
type: Schema.ObjectId,
require: true,
ref: "List"
},
allocations: [
{
type: Number,
required: true
}
]
}
],
createdAt: {
type: Date,
"default": Date.now
},
updatedAt: {
type: Date
}
});
exports = module.exports = mongoose.model("Portfolio", schema);
However, I cannot get populate
to work as expected without getting a TypeError: Cannot read property 'ref' of undefined
. I've tried populate('list')
and populate('lists list')
but I'm either not calling things correctly or my Schema isn't formed correctly. I don't have this problem if I simply reference the lists by themselves:
lists: [
{
type: Schema.ObjectId,
require: true,
ref: "List"
}
]
but I want to have the allocations array alongside each list. What do I need to do to get the behavior I want?
Javascript Solutions
Solution 1 - Javascript
I found the answer: populate('lists.list')
works. Thanks to this question: https://stackoverflow.com/questions/14594511/mongoose-populate-within-an-object?rq=1
Solution 2 - Javascript
lists: [
{
list: {
type: Schema.ObjectId,
require: true,
ref: "List"
},
allocations: [
{
type: Number,
required: true
}
]
}
],
=> Because it's an array of objects, you can do this -: Portfolio.populate('lists.list');
lists: [
{
type: Schema.ObjectId,
require: true,
ref: "List"
}
]
=> Because it's an array, you just have to do this -: Portfolio.populate('lists');
Solution 3 - Javascript
Actual answer:
Use this,
populate('lists.list')
Extra:
Here are lists are an array of objects (list). In JS you can access this like that,
console.log(lists.list);
and MongoDB syntax is 99% similar to JS syntax. so....................
Solution 4 - Javascript
if you have nested schema
YourSchema.find()
.populate({
path: 'map_data',
populate: {
path: 'location'
}
})
it's work for me
Solution 5 - Javascript
// Cart schema
var CartSchema = new mongooseSchema({
productDetails: [{
productId: {
type: mongoose.Schema.ObjectId,
required: true,
ref: 'Product'
},
productCount: Number,
}],
UserId: {
type: String,
default: '',
required: true,
trim: true,
},
shopId: {
type: String,
default: '',
required: true,
trim: true,
},
});
// add this .populate('productDetails.productId').
db.Cart.find({
UserId: userId,
shopId: shopId
}).populate('productDetails.productId')
.skip(pagination.skip)
.limit(pagination.limit)
.exec(function(error,
CartList) {
if (error) {
callback(error, null)
} else {
callback(null, CartList)
}
});
Solution 6 - Javascript
Populate didn't work in my case when nesting to array my Schema was
const chatSchema = mongoose.Schema({
chats: [
{
type: Schema.Types.ObjectId,
ref: "ChatMsg" },
],
})
How I solved it
Chat.findOne(
{ customer: req.body.customer, agency: req.body.agency },
(err, chat) => {
if (err) {
res.status(422).send("Our fault");
}
chat.populate("chats").execPopulate(() => {
res.send(chat);
});
}
);