I have the following code for the models
// rooms model
const mongoose = require('mongoose');
const ObjectId = mongoose.Schema.Types.ObjectId;
// Model
module.exports = mongoose.model('rooms', {
type_id: {
type: ObjectId,
ref: 'types',
required: true,
},
number: {
type: Number,
required: true,
},
});
// types model
const mongoose = require('mongoose');
//Model
module.exports = mongoose.model('types', {
name: {
type: String,
required: true,
trim: true,
},
price: {
type: Number,
required: true,
},
people: {
type: Number,
required: true,
},
images: [String],
details: {
type: String,
required: true,
trim: true,
},
});
For the get request, I have.
router.get('/', async (req, res) => {
console.log(req.query);
Rooms.find(req.query)
.populate({ path: 'types', select: 'name price people images details' })
.then((data) => {
console.log(data);
res.send(data);
})
.catch((err) => {
res.send(err);
});
});
I am trying to populate to achieve the following results as the room with its type as name price people image details, unfortunately, I only get the following. Any help would be appreciated. Thanks
[
{
"_id": "5e88e3107f10f555cffc36c9",
"type_id": "5e88cb8360363053b67c3f85",
"number": 103,
"__v": 0
}
]
Related
when i "console.log(req.product.photo.data)" i have got whole product details there photo related details are first then others(_id, name, description etc) but i need only photo data. but in postman got right image.
router request-->
router.get("/product/photo/:productId",photo);
product model-->
const mongoose = require("mongoose");
const { ObjectId }=mongoose.Schema;
const productSchema = new mongoose.Schema({
name: {
type: String,
trim: true,
required: true,
maxlegth: 32,
},
description: {
type: String,
required: true,
maxlegth: 2000
},
price: {
type: Number,
trim: true,
required: true,
maxlegth: 32
},
price: {
type: Number,
trim: true,
required: true,
maxlegth: 32
},
category:{
type: ObjectId,
ref:'Category',//refer to category models
required:true
},
quantity:{
type:Number,
},
sold:{
type:Number,
default:0
},
photo:{
data:Buffer,
contentType:String
},
shipping:{
required:false,
type:Boolean
}
},
{timestamps:true}
);
photo function code in product controller-->
exports.photo=(req,res,next)=>{
console.log(req.product.photo.data);
if(req.product.photo.data)
{
res.set("Content-Type",req.product.photo.contentType);
return res.send(req.product.photo.data);
}
next();
}
productById middleware code in product controller-->
exports.productById = (req, res, next, id) => {
Product.findById(id).exec((err, product) => {
if (err || !product) {
return res.status(400).json({
error: "Product not found",
});
}
req.product = product;
next();
});
};
here's the booking schema
const bookingSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
routeId:{
type: mongoose.Schema.Types.ObjectId,
ref: "Route",
required: true,
}
})
In this table the routeId(route schema) contains the Bus table(referenced).
const routeSchema = new mongoose.Schema({
location:{
type: mongoose.Schema.Types.ObjectId,
ref: 'Location',
required: true
},
duration: {
type: Number,
required: true
},
Bus:{
type: mongoose.Schema.Types.ObjectId,
ref:"Bus",
required: true
},
date: {
type:String,
required: true
},
},
{
timestamps: true,
});
and then finally the bus model
const busSchema = new mongoose.Schema(
{
busNumber: {
type: String,
unique: true,
required: true,
},
seats: {
type: Number,
},
},
{
timestamps: true,
}
);
Now I want to show only bus number and not whole bus data. this is the response I am getting. https://i.stack.imgur.com/S1qyZ.png
this is the query that I applied.
router.get("/bus/myBooking/one/:id", auth, async (req, res) => {
const _id = req.params.id;
const myBooking = await Booking.findById({ _id })
.populate({path: 'routeId', populate: 'Bus'})
.select(["-_id","-userId","-createdAt","-updatedAt","-__v","-passengers._id","-departureDetails._id","-arrivalDetails._id"]);
try {
return !myBooking
? res.status(404).send("No booking found")
: res.status(200).send(myBooking);
} catch (e) {
res.status(500).send();
}
});
This method works on some versions of mongoose, So you can try this:
await Booking.findById({ _id })
.populate({
path: 'routeId',
populate: {
path: 'Bus',
model: Bus,
select:"-_id busNumber"
}
})
I have a problem in populate method in mongodb it can't retrieve data from model. Can anyone help me solve that problem?
This is the code
router.get('/', auth, async (req, res) => {
try {
const user = req.user._id;
const wishlist = await Wishlist.find({ user, isLiked: true })
.populate({
path: 'Products',
select: 'title',
})
.sort('-updated');
res.status(200).json({
wishlist,
});
} catch (error) {
res.status(400).json({
error: 'Your request could not be processed. Please try again.',
});
}
});
When I navigate to http://localhost:3000/wishlist/, this is the response I get:
{
"wishlist": [
{
"product": "60cb5eb82cc7091ae2e31c88",
"user": "60cb6c46291247466fe08f92",
"isLiked": true,
"_id": "60d1a656567e08bf89571209",
"updated": "2021-06-22T10:09:25.295Z",
"created": "2021-06-22T08:59:02.434Z",
"__v": 0
}
]
}
The model of products
const mongoose = require('mongoose');
const { Schema } = mongoose;
const ProductSchema = mongoose.Schema({
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
category:{
type: Schema.Types.ObjectId,
ref: 'Categories',
default: null
},
photo: { type: String, required: true },
createdAt: {
type: Date,
default: new Date(),
},
updateAt: Date,
price: {
type: String,
required: true,
},
quantity: {
type: Number
}
,
isActive: {
type: Boolean,
default: true
},
user: {
type: Schema.Types.ObjectId,
ref: "User",
}
});
module.exports = mongoose.model('Product', ProductSchema);
The model for wishlist:
const Mongoose = require('mongoose');
const { Schema } = Mongoose;
// Wishlist Schema
const WishlistSchema = new Schema({
product: {
type: Schema.Types.ObjectId,
ref: 'Product',
default: null,
},
user: {
type: Schema.Types.ObjectId,
ref: 'User',
default: null,
},
isLiked: {
type: Boolean,
},
updated: {
type: Date,
default: Date.now,
},
created: {
type: Date,
default: Date.now,
},
});
module.exports = Mongoose.model('Wishlist', WishlistSchema);
Can anyone help me please to find the solution for that problem?
THIS PROBLEM IS A LITTLE LONGER. SO I TYPED BOLD THE CRITICAL INFORMATIONS FOR YOU.
I develop a project like stackoverflow. I have 4 databases which are:
problems
users
solutions
comments
I referrenced these schemas each other. Here is the Schemas:
Problem Schema
const problemSchema = new mongoose.Schema({
title: {
type: String,
required: [true, 'You have to enter a title']
},
content: {
type: String,
required: [true, 'You have to enter a content']
},
createdAt: {
type: Date,
default: Date.now()
},
slug: {
type: String
},
solution: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Solution'
},
],
comment: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}
],
votes: {
type: Number,
default: 0
},
views: {
type: Number,
default: 0
},
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
}
})
module.exports = mongoose.model('Problem', problemSchema)
User Schema:
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: [true, 'You have to enter an email'],
unique: true,
match: [
/^([\w-\.]+#([\w-]+\.)+[\w-]{2,4})?$/,
'Please provide a valid email address.'
]
},
password: {
type: String,
required: [true, 'You have to enter a password'],
minlength: [6, 'Your password cannot be less than 6 character.'],
select: false
},
role: {
type: String,
default: 'user',
enum: ['user', 'admin']
},
createdAt: {
type: Date,
default: Date.now()
},
about: {
type: String
},
place: {
type: String
},
age: {
type: Number
},
blocked: {
type: Boolean,
default: false
},
problem: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Problem'
},
],
solution: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Solution'
}
],
comment: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'Comment'
}
]
})
and Comments Schema:
const commentSchema = new mongoose.Schema({
content: {
type: String,
required: [true, 'You have to enter a content']
},
createdAt: {
type: Date,
default: Date.now()
},
isFunctional: {
type: Boolean,
default: false
},
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
},
problem: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Problem'
},
})
module.exports = mongoose.model('Comment', commentSchema)
In my project, I send problems into MongoDB. Then I send comment. After save comments, I add these comments into problems and user DB with a function.
function that comments are saved in DB:
const Comment = require('../models/comment/Comment')
const Problem = require('../models/problem/Problem')
const User = require('../models/user/User')
const asyncErrorWrapper = require('express-async-handler')
const addCommentToProblem = asyncErrorWrapper(async (req, res, next) => {
const {content, problemId} = req.body
const newComment = await Comment.create({
content: content,
problem: problemId,
user: req.user.id,
})
const problemOfComment = await Problem.findByIdAndUpdate(problemId, {
$push: { comment: newComment._id }
})
const userOfComment = await User.findByIdAndUpdate(req.user.id, {
$push: { comment: newComment._id }
})
})
Okey everything is so far so good. The problem comes here. When I try to get a problem, I populate some fields for example user fields. So I can add user information in this detail of problem. When populate user and comment in problem schema, it sends me the data. Still, we're ok. But when I try to get user field in comments, it doesn't populate user. It turns just objectId of user information.
Here is the function that I get problem:
const getAProblem = asyncErrorWrapper(async (req, res, next) => {
const {id} = req.params
const problems = null
await Problem.findByIdAndUpdate(id, {
$inc: { views: 1 }
}, { new: true })
.populate('user') ==> THIS LINE WORKS
.populate('comment') ==> THIS LINE WORKS
.populate('comment.user') ==> THIS LINE DOES NOT WORK
.exec(function(err, post) {
if(err) {
console.log(err)
}
res
.status(200)
.json({
success: true,
data: post
})
});
})
Thanks for reading and your patience. Any help will be appreciated.
See doc at https://mongoosejs.com/docs/populate.html
And try this way.
const getAProblem = asyncErrorWrapper(async (req, res, next) => {
const {id} = req.params
const problems = null
await Problem.findByIdAndUpdate(id, {
$inc: { views: 1 }
}, { new: true })
.populate('user') ==> THIS LINE WORKS
.populate({
'path': 'comment',
'populate': {
'path':'user'
}
})
.exec(function(err, post) {
if(err) {
console.log(err)
}
res
.status(200)
.json({
success: true,
data: post
})
});
})
//this error appear
{
"error": {
"message": "Cast to ObjectId failed for value \"events\" at path \"_id\" for model \"user\"",
"name": "CastError",
"stringValue": "\"events\"",
"kind": "ObjectId",
"value": "events",
"path": "_id"
}
}
//when execute this code
exports.get_all_events = (req, res, next) => {
Event.find({})
.populate("creator","name _id",user) // must define model reference
.then(result => {
console.log(result);
res.status(200).json({ result });
}).catch(err => {
console.log(err);
res.status(500).json({ error: err });
});
}
Event schema
const mongoose = require('mongoose');
// creat event schema
const eventSchema = mongoose.Schema({
name: {
type: String,
required: [true, 'name is required']
},
location: {
type: String,
required: [true, 'location is required']
},
date: {
type: String,
required: [true, 'data is required']
},
description: {
type: String,
required: [true, 'description is required']
},
creator: {
_id: {
type: mongoose.Schema.Types.ObjectId,
ref: "users"
}
}
});
module.exports = mongoose.model("events", eventSchema);
Userschema
const mongoose = require('mongoose');
const userSchema = mongoose.Schema({
email: {
type: String,
required: true,
unique: true,
match: /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/
},
password: {
type: String,
required: true
},
name: {
type: String,
required: true
},
post: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "posts"
}
],
event: [
{
type: mongoose.Schema.Types.ObjectId,
// it point to collection
ref: "events"
}
]
});
module.exports = mongoose.model('users', userSchema);
it works great adding event to database and get single event it work but when i get all events from database throw casting error and can't make any updating on exist event
I think you are populating the events document little bit wrong.
Try this:
Event.find({})
.populate("creator._id","name _id")
.then(result => {
console.log(result);
res.status(200).json({ result });
}).catch(err => {
console.log(err);
res.status(500).json({ error: err });
});
I dont think you need any third argument in the .populate() function, You have already defined in your schema, where it should be populated from:
//look here, you have already defined it in your schema
creator: {
_id: {
type: mongoose.Schema.Types.ObjectId,
ref: "users" //this says which collection it should be populated from
}
}
I hope it helps you out.