Mongoose population problem, how to populate another document - javascript

How to populate comment's (postedBy, votes, replies) on get req of the feature. Each feature has comments and Each comment has postedBy, replies, votes
my feature controller for getting single Feature
exports.getSingleFeature = (req, res) => {
try {
const { slug } = req.params;
Feature.findOne({ slug: slug.toLowerCase() })
.populate("postedBy", " email _id username")
.populate("comments", "content postedBy votes replies")
.populate("comments.postedBy", "_id email username")
.populate("postedBy", "_id email username")
.populate("")
.exec((err, feature) => {
if (err) {
return res.status(400).json({
error: errorHandler(err),
return res.json(feature);
catch (error) {
return res.status(400).json({
error: error,
};
My comment controller-
exports.createComment = (req, res) => {
const { featureId } = req.params;
const { content } = req.body;
const postedBy = req.auth._id;
if (!content) {
return res
.status(400)
.send({ error: "Please provide a content with your comment." });
}
const comment = new Comment({
content,
postedBy,
});
comment.save((err, result) => {
if (err) {
return res.status(400).json({
error: errorHandler(err),
});
}
Feature.findByIdAndUpdate(
featureId,
{ $push: { comments: result } },
new: true }
).exec((err, result) => {
if (err) {
return res.json({
error: errorHandler(err),
});
}
});
return res.status(201).json(result);
});
};
My Feature Model -
const mongoose = require("mongoose");
const { ObjectId } = mongoose.Schema;
const featureSchema = new mongoose.Schema(
title: {
type: String,
required: true,
min: 5,
max: 40,
trim: true,
unique: true,
type: {
type: String,
trim: true,
description: {
type: String,
required: true,
min: 25,
max: 400,
trim: true,
slug: {
type: String,
unique: true,
index: true,
excerpt: {
type: String,
required: true,
min: 10,
max: 120,
trim: true,
postedBy: {
type: ObjectId,
ref: "User",
comments: [
type: ObjectId,
ref: "Comment",
likes: [{ type: ObjectId, ref: "User", required: true }],
timestamps: true }
module.exports = mongoose.model("Feature", featureSchema);
MY comment Model-
const mongoose = require("mongoose");
const { ObjectId } = mongoose.Schema;
const commentSchema = new mongoose.Schema(
{
content: {
type: String,
required: true,
trim: true,
max: 200,
},
postedBy: {
type: ObjectId,
ref: "User",
required: true,
},
votes: [
{
postedBy: {
type: ObjectId,
ref: "User",
},
created: {
type: Date,
default: Date.now,
},
},
],
replies: [
{
content: {
type: String,
required: true,
trim: true,
max: 200,
},
postedBy: {
type: ObjectId,
ref: "User",
},
created: {
type: Date,
default: Date.now,
},
votes: [
{
postedBy: {
type: ObjectId,
ref: "User",
},
created: {
type: Date,
default: Date.now,
},
},
],
},
],
},
timestamps: true }
);
module.exports = mongoose.model("Comment", commentSchema);```
I am getting this on postman -
enter image description here

Related

Mongoose populate() is returning an empty array

I am trying to use mongoose populate function but in response I am getting empty array. I know there are several questions talking about the same subject but none worked for my case.
My objective is to populate my Order document.
This is how my schemas are organized:
Menu.js
const mongoose = require("mongoose");
const { Schema } = mongoose;
const Food = require("./Food");
const Drink = require("./Drink");
const MenuSchema = new Schema({
code: {
type: mongoose.ObjectId,
required: true,
unique: true,
},
name: {
type: String,
required: true,
},
food: {
type: [Food.schema],
required: false,
},
drinks: {
type: [Drink.schema],
required: false,
},
type: {
type: String,
},
createdAt: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model("Menu", MenuSchema);
Note: Im using Food.schema and Drink.schema inside my Arrays instead of making a ref. Im storing the Food and Drink models inside of the Menu model
Food.js
const mongoose = require("mongoose");
const { Schema } = mongoose;
const FoodSchema = new Schema({
code: {
type: mongoose.ObjectId,
required: true,
unique: true,
},
description: {
type: String,
required: true,
},
ingredients: {
type: [],
required: false,
default: [],
},
stock: {
type: Number,
required: true,
},
type: {
type: String,
enum: ["starter", "main", "dessert"],
required: true,
},
price: {
type: Number,
required: true,
},
createdAt: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model("Food", FoodSchema);
Drink.js
const mongoose = require("mongoose");
const { Schema } = mongoose;
const DrinkSchema = new Schema({
code: {
type: mongoose.ObjectId,
required: true,
unique: true,
},
description: {
type: String,
required: true,
},
stock: {
type: Number,
required: true,
},
price: {
type: Number,
required: true,
},
createdAt: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model("Drink", DrinkSchema);
Order.js
const mongoose = require("mongoose");
const { Schema } = mongoose;
const OrderSchema = new Schema({
code: {
type: mongoose.ObjectId,
required: true,
unique: true,
},
type: {
type: String,
required: true,
enum: ["restaurant", "takeaway", "delivery"],
},
food: {
type: [{ type: mongoose.ObjectId, ref: "Food" }],
required: false,
default: [],
},
drinks: {
type: [{ type: mongoose.ObjectId, ref: "Drink" }],
required: false,
default: [],
},
orderValue: Number,
client_id: {
type: mongoose.ObjectId,
ref: "Client",
required: false,
},
createdAt: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model("Order", OrderSchema);
This is the controller where I'm trying to make my populate work. Whenever I remove the populate method I get the _id references for the Food and Drink arrays.
TableController.js
exports.getOrderFromTable = async (req, res) => {
const { code, tableCode } = req.params;
try {
const foundRestaurant = await Restaurant.findOne({ code: code });
const foundTable = foundRestaurant.tables.filter(
(table) => table.code == tableCode
);
console.log(foundTable[0].order_id);
const foundOrder = await Order.findOne({
_id: foundTable[0].order_id,
})
.populate("food")
.populate("drinks");
res.send(foundOrder);
} catch (err) {
res.json({ message: err });
}
};
And this is what the mongoose debugger returns when I run the controller:
Mongoose: restaurants.findOne({ code: new ObjectId("62a60dcb9fe25d276815675c") }, { projection: {} })
new ObjectId("62a60ece9fe25d27681567b7")
Mongoose: orders.findOne({ _id: new ObjectId("62a60ece9fe25d27681567b7") }, { projection: {} })
Mongoose: foods.find({ _id: { '$in': [ new ObjectId("62a60e039fe25d276815677d"), new ObjectId("62a60e169fe25d2768156785") ], [Symbol(mongoose#trustedSymbol)]: true }}, { skip: undefined, limit: undefined, perDocumentLimit: undefined, projection: {}})
Mongoose: drinks.find({ _id: { '$in': [ new ObjectId("62a60e259fe25d276815678d"), new ObjectId("62a60e3c9fe25d276815679c") ], [Symbol(mongoose#trustedSymbol)]: true }}, { skip: undefined, limit: undefined, perDocumentLimit: undefined, projection: {}})
And finally this is the JSON file I get when I do a GET http request using Postman:
{
"_id": "62a60ece9fe25d27681567b7",
"code": "62a60ece9fe25d27681567b6",
"type": "restaurant",
"food": [],
"drinks": [],
"orderValue": 25,
"createdAt": "2022-06-12T16:05:34.513Z",
"__v": 0
}
Thank you for any help. I've been really struggling with this method.

MissingSchemaError: Schema hasn't been registered for model UserAddress.address

Been pulling my hair out for hours now, just can't figure out why the field refuses to populate.
What I want to do is return the AddressId field populated with values instead of just an ID, but nothing I've tried works, none of the solutions I found do anything.
If you need any other code from the project, I will update the question.
Any help is highly appreciated.
Order Model:
const mongoose = require("mongoose");
const orderSchema = new mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
addressId: {
type: mongoose.Schema.Types.ObjectId,
ref: "UserAddress.address",
required: true,
},
totalAmount: {
type: Number,
required: true,
},
items: [
{
productId: {
type: mongoose.Schema.Types.ObjectId,
ref: "Product",
},
payablePrice: {
type: Number,
required: true,
},
purchasedQty: {
type: Number,
required: true,
},
},
],
paymentStatus: {
type: String,
enum: ["Pending", "Completed", "Cancelled", "Refund"],
required: true,
},
paymentType: {
type: String,
enum: ["CoD", "Card", "Wire"],
required: true,
},
orderStatus: [
{
type: {
type: String,
enum: ["Ordered", "Packed", "Shipped", "Delivered"],
default: "Ordered",
},
date: {
type: Date,
},
isCompleted: {
type: Boolean,
default: false,
},
},
],
},
{ timestamps: true }
);
module.exports = mongoose.model("Order", orderSchema);
Address Model:
const mongoose = require("mongoose");
const addressSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true,
min: 10,
max: 60,
},
mobileNumber: {
type: String,
required: true,
trim: true,
},
pinCode: {
type: String,
required: true,
trim: true,
},
locality: {
type: String,
required: true,
trim: true,
min: 10,
max: 100,
},
address: {
type: String,
required: true,
trim: true,
min: 10,
max: 100,
},
cityDistrictTown: {
type: String,
required: true,
trim: true,
},
state: {
type: String,
required: true,
required: true,
},
landmark: {
type: String,
min: 10,
max: 100,
},
alternatePhone: {
type: String,
},
addressType: {
type: String,
required: true,
enum: ["home", "work"],
required: true,
},
});
const userAddressSchema = new mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: "User",
},
address: [addressSchema],
},
{ timestamps: true }
);
mongoose.model("Address", addressSchema);
module.exports = mongoose.model("UserAddress", userAddressSchema);
Code that runs the query:
const Order = require("../models/order");
const Cart = require("../models/cart");
const Address = require("../models/address");
const Product = require("../models/product");
exports.getOrders = (req, res) => {
Order.find({ user: req.user._id })
.select("_id paymentStatus paymentType orderStatus items addressId")
.populate("items.productId", "_id name productImages")
.populate("addressId")
.exec((error, orders) => {
if (error) {console.log(error)
return res.status(400).json({ error });}
if (orders) {
res.status(200).json({ orders });
}
});
};

I can't figure out how to populate dynamic reference in mongoose

This is my user model code. I am referencing the favorites using dynamic referencing as there are three types of posts that can be added to favorites
import mongoose from 'mongoose'
import bcrypt from 'bcryptjs'
const userSchema = mongoose.Schema(
{
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
isAdmin: {
type: Boolean,
required: true,
default: false,
},
contact:{
type:Number,
required: true,
unique:true
},
cnic: {
type: Number,
required: true,
unique: true
},
favorites: [
{
postType: {
type: String
},
postId: {
type: mongoose.Schema.Types.ObjectId,
refPath: 'postType'
},
}
],
itemsRented: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Rent',
}
],
itemsRentedOut: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Rent',
}
],
collectionRequestsSent: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'CommunityService',
}
],
itemsCollected: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'CommunityService',
}
],
servicesOrdered: [
{
type:mongoose.Schema.Types.ObjectId,
ref: 'Services'
}
],
paymentDetails: {
card: { type: Number },
cvc: { type: Number },
name: { type: String },
email: {type: String },
expiryDate: {
month: { type: Number },
year: { type: Number }
},
},
address: { type: String },
isDisputeResolutionStaff: {
type: String,
default: false
}
},
{
timestamps: true,
}
)
userSchema.methods.matchPassword = async function (enteredPassword) {
return await bcrypt.compare(enteredPassword, this.password)
}
userSchema.pre('save', async function (next) {
if (!this.isModified('password')) {
next()
}
const salt = await bcrypt.genSalt(10)
this.password = await bcrypt.hash(this.password, salt)
})
const User = mongoose.model('User', userSchema)
export default User
This is my controller. I want to get the posts' details added to favorites by using populate but when I run the code it returns the user object not the post details
const getFavorites = asyncHandler(async(req,res) => {
await User.
findById("61b51adfb7b8a64fd87420d3").
populate("favorites").
exec(function (err, story) {
if (err) throw new Error(err);
console.log(story);
});
})

Mongoose adding values to an array

How can I add a User to the School's admins field?
School Schema:
const School = new Schema({
name: { type: String, required: true },
grades_primary: [{ type: Schema.Types.ObjectId, ref: 'Grade' }],
grades_secondary: [{ type: Schema.Types.ObjectId, ref: 'Grade' }],
admins: [{ type: Schema.Types.ObjectId, ref: 'User' }]
})
User Schema
const User = new Schema({
complete_name: { type: String, required: true, },
password: { type: String, required: true },
nombre_de_usuario: { type: String, unique: true, required: true },
email: { type: String, unique: true, required: true },
})
I tried this but it didn't work:
const saved_user = await user.save()
created_school.admins.push(saved_user)
await created_school.save()
use $push
const saved_user = await user.save()
try {
const created_school= await School.findOneAndUpdate({ _id: '1' }, { $push: { admins: saved_user } })
// ....
} catch (error) {
console.log(error);
}

Populate in nested schema Mongoose

I have this User model:
const userSchema = new Schema({
_id: {
type: Schema.Types.ObjectId,
required: true
},
name: {
type: String,
required: true
},
email: {
type: String,
unique: true,
required: true
},
notification: {
experiment_id: {
type: Schema.Types.ObjectId,
ref: "Experiment",
required: false
},
seen: {
type: Boolean,
required: true,
default: false
}
}
});
And this Experiment model:
const experimentSchema = new Schema(
{
_id: {
type: Schema.Types.ObjectId,
required: true
},
name: {
type: String,
required: true
},
description: {
type: String,
required: true,
default: "No Description"
},
author_id: {
type: Schema.Types.ObjectId,
ref: "User",
required: true
}
);
I am trying to populate from User the experiment_id in notification.
And from this populate, I would like to populate the author_id as well.
I have seen some code like I have done below but I didn't succeed.
I am trying this:
User.find(
{
_id: req.params.currentUserId
},
"notification"
)
.populate({ path: "experiment_id", populate: { path: "author_id" } })
.exec((err, notif) => {
});
I fixed it by adding notification.experiment_id in the path
User.find(
{
_id: req.params.currentUserId
},
"notification"
)
.populate({ path: "notification.experiment_id", populate: { path: "author_id" } })
.exec((err, notif) => {
});

Categories

Resources