I have an Order model:
const orderSchema = new mongoose.Schema({
order_items: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'OrderItem',
required: true
}],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
shipping_address: {
type: String,
required: true
},
total_price: {
type: Number
}
});
And OrderItem model:
const orderItemSchema = new mongoose.Schema({
product_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Product',
required: true
},
quantity: {
type: Number,
required: true
},
unit_price: {
type: Number,
required: true
}
});
And Product model:
const productSchema = new mongoose.Schema({
name: {
type: Map,
of: String,
required: true
},
unit_price: {
type: Number,
required: true
}
});
I tried to do double populate on find Order in the request like this:
const findOrder = await Order.find({ user: user_id }).populate('order_items').populate({ path: 'order_items.product_id', select: 'name' });
But I get only the first populate. When I tried the following:
const findOrder = await Order.find({ user: user_id }).populate('order_items').populate({ path: 'product_id', select: 'name' });
I got this error:
Cannot populate path product_id because it is not in your schema.
Set the strictPopulate option to false to override.
How can I get the product's name in a nested populate request?
Thanks...
Try with:
const findOrder = await Order.find({ user: user_id })
.populate({
path: 'order_items',
populate: {
path: 'product_id',
select: 'name'
}
}).exec();
For more information about the population across multiple levels read here.
Related
I have a database containing 3 collections [Users (contains registered users), Userpost (contains the post of the registered users) while Profile (contains their individual profile)].
I was able to link the Profile and Users Schemas to the Userpost Schema with their ObjectId.
What I know at present is how to fetch the Userpost and populate the User and Profile.
What I want to do is to fetch all the post of a single registered user his/her timeline.
What I have tried to the add the Userpost and Profile Schemas to the UserSchema by the ObjectId but each time I make a post, the Userpost on the User collection is always an empty array.
Below are my Schemas please
User Schema
const userSchema = new Schema({
username: {
type: String,
required: true
},
roles: {
User: {
type: Number,
default: 2001
},
Mentor: Number,
Admin: Number
},
password: {
type: String,
required: true
},
userID: {
type: String,
required: true
},
refreshToken: String
});
const User = mongoose.model('user', userSchema);
module.exports = User;
Profile Schema
const ProfileSchema = new Schema({
lastname: {
type: String,
required: true,
},
firstname: {
type: String,
required: true,
},
othernames: {
type: String,
required: true,
},
countries: {
type: String,
required: true,
},
phones: {
type: String,
required: true,
},
User: [{
type: Schema.Types.ObjectId,
ref: 'user',
required: true,
}],
});
const Profile = mongoose.model('profile', ProfileSchema);
module.exports = Profile;
UserPost Schema
const UserpostSchema = new Schema({
post: {
type: String,
required: true
},
Profile: [{
type: Schema.Types.ObjectId,
ref: 'profile',
required: true,
}],
User: [{
type: Schema.Types.ObjectId,
ref: 'user',
required: true,
}]
});
const Userpost = mongoose.model('userpost', UserpostSchema);
module.exports = Userpost;
How I populate User and Profile to the UserPost on API
router.get('/getpost/:id', (req, res) => {
const id = req.params.id;
Userpost.find({_id:id}).populate('User').populate('Profile').exec((err,docs) => {
if(err) throw(err);
res.json(docs);
})
});
How do I fetch the entire post of a user to his timeline?
Kindly help please.
Thanks and regards
This should work for u, In UserPost Schema you have taken array for Profile and User which isn't required, and also instead of Schema use mongoose.Schema every where in model.
User Schema
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true
},
roles: {
User: {
type: Number,
default: 2001
},
Mentor: Number,
Admin: Number
},
password: {
type: String,
required: true
},
userID: {
type: String,
required: true
},
refreshToken: String
});
const User = mongoose.model('user', userSchema);
module.exports = User;
Profile Schema
const mongoose = require("mongoose");
const ProfileSchema = new mongoose.Schema({
lastname: {
type: String,
required: true,
},
firstname: {
type: String,
required: true,
},
othernames: {
type: String,
required: true,
},
countries: {
type: String,
required: true,
},
phones: {
type: String,
required: true,
},
User: {
type: mongoose.Schema.Types.ObjectId,
ref: "user",
required: true,
},
});
const Profile = mongoose.model('profile', ProfileSchema);
module.exports = Profile;
UserPost Schema
const mongoose = require("mongoose");
const UserpostSchema = new mongoose.Schema({
post: {
type: String,
required: true,
},
Profile: {
type: mongoose.Schema.Types.ObjectId,
ref: "profile",
required: true,
},
User: {
type: mongoose.Schema.Types.ObjectId,
ref: "user",
required: true,
},
});
const Userpost = mongoose.model("userpost", UserpostSchema);
module.exports = Userpost;
I have an order model/schema, and my goal is that in this model in "list", I receive the information from the model cart in array format. How could I do this using ref?
cart model
const mongoose = require('mongoose');
const CartSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
},
note: {
type: String,
required: true,
},
price: {
type: Number,
required: false,
},
createdAt: {
type: Date,
default: Date.now,
}
},
{ timestamps: true }
);
module.exports = mongoose.model("Cart", CartSchema);
order
const mongoose = require('mongoose');
const OrderSchema = new mongoose.Schema(
{
list: {
name: String,
notes: String,
},
totalAmount: {
type: Number,
required: true,
},
payment: {
type: String,
required: true,
},
address: {
type: String,
required: true,
},
addressNote: {
type: String,
required: false,
},
createdAt: {
type: Date,
default: Date.now,
}
},
{ timestamps: true }
);
module.exports = mongoose.model("Order", OrderSchema);
Basically receive in array format the information of the model cart in "list" in model order
You should define your list as an array of ObjectIds referring to the Cart model:
const OrderSchema = new mongoose.Schema(
{
list: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Cart'
}],
...
});
Then, to retrieve the values in list, just populate the Order:
Order.find({}).populate('list').exec();
I have the following code inside the file user.model.js in my Node + EpxressJS application's source.
"use strict";
const { ObjectId } = require("bson");
const mongoose = require("mongoose");
const uniqueValidator = require("mongoose-unique-validator");
const wordSchema = new mongoose.Schema({
word: { type: String, trim: true },
match: { type: String, enum: ["exact", "startsWith", "endsWith", "contains"] }
});
const muteSchema = new mongoose.Schema({
users: [{ type: ObjectId, ref: "User" }],
words: [{ type: wordSchema }],
posts: [{ type: ObjectId, ref: "Post" }]
});
const userSchema = new mongoose.Schema(
{
handle: { type: String, trim: true, required: true, unique: true },
password: { type: String, trim: true, required: true, select: false },
posts: [{ type: ObjectId, ref: "Post", select: false }],
favourites: [{ type: ObjectId, ref: "Post", select: false }],
following: [{ type: ObjectId, ref: "User", select: false }],
followers: [{ type: ObjectId, ref: "User", select: false }],
muteList: { type: muteSchema, select: false },
blockList: [{ type: ObjectId, ref: "User", select: false }],
isDeactivated: { type: Boolean, default: false },
isDeleted: { type: Boolean, default: false }
},
{
timestamps: true
}
);
userSchema.plugin(uniqueValidator);
module.exports = mongoose.model("User", userSchema);
I create a new user using the User model like this:
const user = new User({ handle: "asdf", password: "[passwordHash]" });
await user.save();
Now when I run db.users.find(), all the other fields exist in the database, except muteList. Why is this happening?
Okay, figured it out. I just needed to provide a default value.
muteList: { type: muteSchema, default: {}, select: false }
I am trying to sort populated array based on the nested and populated field using mongoose but it is not working.
Here are my modals.
const campaignSchema = new Schema(
{
name: { type: String, required: true },
prospects: [{ type: mongoose.Types.ObjectId, ref: "Prospect" }],
}
);
const prospectSchema = new Schema(
{
strategy: { type: String, trim: true },
contact: { type: mongoose.Types.ObjectId, ref: "Contact", required: true },
primaryCaller: { type: mongoose.Types.ObjectId, ref: "Contact" },
}
);
const contactSchema = new Schema(
{
firstName: { type: String, required: true },
lastName: { type: String, required: true },
}
);
Now I am trying to populate prospects and contact in each prospect in and sort them by contact.firstName using the following code.
const campaign = await Campaign.findOne({ _id: id }).populate({
path: "prospects",
populate: [
{ path: "contact", select: "firstName lastName" },
{ path: "primaryCaller", select: "firstName lastName" },
],
options: {
sort: "contact.firstName",
},
}).lean();
I tested it with sort: "strategy", and it is working fine with it.
I also tried Aggregations but it also didn't help.
I'm looking to make a populate() on a find() request but specifying multiple models, so if no occurrence is found on the first specified model the population will make on the second.
Here is an example of what I would like to do :
const userSch = new Schema({
username: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
mail: {
type: String,
required: true,
unique: true,
}
});
const botSch = new Schema({
username: {
type: String,
required: true,
},
token: {
type: String,
required: true,
unique: true,
},
owner: mongoose.Schema.Types.ObjectId
});
const nspSch = new Schema({
name: String,
channels: [channels],
users: [{
id: {
type: mongoose.Schema.Types.ObjectId,
},
bot: {
type: Boolean,
}
}],
});
const channels = new Schema({
name: String,
message: [{
user: {
type: Schema.Types.ObjectId,
},
content: String,
}],
});
const nsp = mongoose.model('namespace', nspSch);
const Auth = mongoose.model('users', userSch);
const BotAuth = mongoose.model('bots', botSch);
function returnMs(nspID, channelID, callback) {
nsp.findOne({'_id': nspID}).populate({
path: 'channels.message.user',
model: 'users' || 'bots',
select: '_id username',
})
.exec(function(err, r) {
...
})
}
If there is ever an npm package, or a solution or even a track to code it, please share it.
Thank you