I am trying to build a forum and have come across some problems when trying to add answers with information of the user to a specific post. I am able to list the answers for a single post in the frontend, however I am unable to populate the user information, as for now I only get an id. Here are my models and endpoints to post and get the answers. What am I missing?
const User = mongoose.model('User', {
username: {
type: String,
required: [true, 'Username is required!'],
unique: true,
lowercase: true,
trim: true
},
email: {
type: String,
required: [true, 'Email is required!'],
unique: true,
lowercase: true,
trim: true,
validate: {
validator: (value) => {
return /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(value)
},
message: "Please enter a valid email address"
}
},
password: {
type: String,
required: [true, 'Password is required!'],
minlength: [8, 'Password must be a minimum of 8 characters!']
},
accessToken: {
type: String,
default: () => crypto.randomBytes(128).toString('hex')
}
})
const Post = mongoose.model('Post', {
title: {
type: String,
required: [true, 'Field cannot be blank'],
minlength: [2, 'Your post must be a minimum of 2 characters!'],
maxlength: [50, 'Your post must be a maximum of 50 characters!']
},
post: {
type: String,
required: [true, 'Field cannot be blank'],
minlength: [2, 'Your post must be a minimum of 2 characters!'],
},
votes: {
type: Number,
default: 0
},
createdAt: {
type: Date,
default: Date.now()
},
answers: [{
type: mongoose.Schema.Types.ObjectId,
ref:'Answer'
}],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
})
const Answer = mongoose.model('Answer', {
answers: {
type: String,
},
number: {
type: Number,
default: 0
},
post: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
createdAt: {
type: Date,
default: Date.now()
}
})
app.get('/posts/:id/answers', authenticateUser, async (req, res) => {
const { id } = req.params
const newAnswer = await Post.findById(id).populate('user', 'username').populate('answers').exec()
res.json({ success: true, newAnswer })
})
app.post('/posts/:id/answers', authenticateUser, async (req, res) => {
const { id } = req.params
const { _id } = req.user
const { answers, post } = req.body
try {
const user = await User.findById(_id)
// get answer and save post id
const newAnswer = new Answer({
answers: req.body.answers,
post: id,
user
})
// save answer
const result = await newAnswer.save()
// find post and push the comment into the array in the same moment
const answeredPost = await Post.findByIdAndUpdate(id, {
$push: {
answers: result
}
}).populate('user', 'username').populate('answers').exec()
res.json({ success: true, answeredPost})
} catch (error) {
res.status(400).json({ success: false, message: 'Invalid request', error })
}
})
Try this:
Post.findById(id).populate('user', 'username').populate({ path : 'answers', populate : { path : 'user'}}).exec()
Related
Is this a proper way to define it?
const mongoose = require("../database");
// create a schema
var userschema =new mongoose.Schema({
name: String,
password: String,
email:String
});
var userModel=mongoose.model('users',userSchema);
module.exports = mongoose.model("Users", userModel);
//Please Try In This Way
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const User = mongoose.Schema(
{
name: {
type: String,
default: "",
trim: true,
},
email: {
type: String,
default: "",
trim: true,
validate: {
validator: async function (email) {
const user = await this.constructor.findOne({ email });
if (user) {
if (this.id === user.id) {
return true;
}
return false;
}
return true;
},
message: (props) => "This email is already in use",
},
required: [true, "User email required"],
},
password: {
type: String,
default: "",
trim: true,
select: false,
},
mobile: {
type: String,
default: "",
trim: true,
},
experience: {
type: String,
default: "",
trim: true,
},
agree: {
type: Array,
default: "",
trim: true,
},
status: {
type: Number,
default: 1,
},
type: {
type: String,
},
isDelete: {
type: Boolean,
default: false,
},
},
{
timestamps: { createdAt: "createdAt", updatedAt: "updatedAt" },
}
);
module.exports = mongoose.model("User", User);
I have a schema that looks like:
const houseSchema = new mongoose.Schema({
address: {
type: String,
required: true,
trim: true,
},
city: {
type: String,
required: true,
},
roofType: {
type: String,
//required: true,
},
repairType: {
type: String,
//required: true,
},
numFloors: {
type: Number,
//required: true,
},
isOwner: {
type: Boolean,
//required: true,
},
isGated: {
type: Boolean
},
includeFlat: {
type: Boolean
},
addedBy: [
{
name:{
type: String
},
time:{
type: String
},
}
],
});
const customerSchema = new mongoose.Schema({
firstName: {
type: String,
required: true,
trim: true,
},
lastName: {
type: String,
required: true,
trim: true,
},
phoneNumber: {
type: String,
required: true,
},
email: {
type: String,
},
//array of houseSchema objects
properties: [
houseSchema
],
});
And my endpoint that is used to update one of the 'properties' is:
router.route('/property').post(async (req,res) => {
const body = req.body;
Customer.updateOne({_id: req.query.id, properties: {$elemMatch: {_id: req.query.pId}}},
{
$set: {
"properties.$.address": body.address,
"properties.$.city": body.city,
"properties.$.roofType": body.roofType,
"properties.$.repairType": body.repairType,
"properties.$.numFloors": body.numFloors,
"properties.$.isOwner": body.isOwner,
"properties.$.isGated": body.isGated,
"properties.$.includeFlat": body.includeFlat
}
},
function(err){
if(err){
res.status(400).json('Error: ' + err);
}
else{
res.json('Property Updated!');
}
}
)
});
The endpoint works mostly fine (it returns the customer and all properties when i only search for and want to modify one of the 'properties') but only when it is a post or a get request and when it is a put request, the error says
Error: ValidationError: firstName: Path firstName is required., lastName: Path lastName is required., phoneNumber: Path phoneNumber is required.
I dont know if its a big deal or not, but I do not know why this is happening and would like to know. Just to be clear, the goal of this endpoint is to find one of the properties and update its values, not to change anything about a customer or any of their other properties.
I am Working in a MERN application. In one of my model of express.js I have student schema like below which have unique fields
Fullname: {
type: String,
required: true,
trim: true,
},
AdmissionNumber: {
type: String,
required: true,
trim: true,
maxlength: 10,
unique: true,
},
RollNumber: {
type: Number,
required: true,
trim: true,
maxlength: 4,
},
Age: {
type: Number,
required: true,
maxlength: 2,
},
Email: {
type: String,
trim: true,
required: true,
unique: true,
},
Faculty: {
type: ObjectId,
ref: "Faculty",
required: true,
},
pass: {
type: Number,
default: 0,
}
I am saving the student with the help of form like this
exports.addStudent = (req, res) => {
let form = new formidable.IncomingForm();
form.keepExtensions = true;
form.parse(req, (err, fields) => {
if (err) {
res.status(400).json({
error: "problem with feilds",
});
}
// destructuring feilds
const {
Fullname,
AdmissionNumber,
RollNumber,
Age,
Email,
Faculty,
} = fields;
if (
!Fullname ||
!AdmissionNumber ||
!RollNumber ||
!Age ||
!Email ||
!Faculty
) {
return res.status(400).json({
error: "Please fill all fields",
});
}
// TODO: restriction on fields
let student = new Student(fields);
student.save((err, student) => {
if (err) {
res.status(400).json({
error: "Saving Student in DB failed",
});
console.log(err);
}
res.json(student);
// console.log(student.gender);
});
});
};
When I try to add student it will be added only first time after that it showing an error
I have checked my DB collection there is only one field in the database.
I had this problem before and the solution that worked for me is to delete the collection from the database then try again
I have a product collection and a user collection where I reference user to my product collection.
So far what I am trying to achieve here is to get only the products that are created by that user.
const getOwnerProduct = expressAsyncHandler(async (req, res) => {
const activeUser = await User.findById(req.user._id)
const pageSize = 10
const page = Number(req.query.pageNumber) || 1
const items = { user: { _id: activeUser } }
const count = await Product.countDocuments({ ...items } )
const products = await Product.find({ ...items }).limit(pageSize).skip(pageSize * (page - 1))
res.json({ products, page, pages: Math.ceil(count / pageSize) })
})
Here's the Product Schema:
const productSchema = mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
},
name: {
type: String,
required: true
},
price: {
type: Number,
required: true,
},
description: {
type: String,
required: true
},
email: {
type: String
},
rating: {
type: Number,
required: true,
default: 0
},
image: {
type: String,
required: true,
default: 0
},
}, { timestamps: true
})
And here's the userSchema:
const userSchema = mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
phone: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
role: {
type: String,
enum: ['administrator', 'productOwner', 'regular'],
default: 'regular'
}
}, { timestamps: true
})
Here's the router:
app.use('/api/products', productRoutes)
router.route('/').get(getProducts, admin).get(getOwnerProducts, productOwner)
For some reason this doesn't work. I think my query on mongodb is not correct.
Any idea what am I missing here?
Here instead of const products = await Product.find({ ...items }) you can try
await User.findById(req.user._id).forEach(element =>{Product.find({user=element._id})});
or
await User.findById(req.user._id).forEach(element =>{Product.find(user=element._id)});
who can explain with example how to get from another schema user data (for example useravatar)
while i read about refs and i cant understand.
This is my code, but i want to send back not only article but with profile datas about author. How can i do this ? I have authorID already for this.
router.post('/get-article', (req, res) => {
const { id, authorID } = req.body.data;
Article.findByIdAndUpdate({ _id: id }, { $inc: { "pageview": 1 } }, (err, article) => {
if (err) return res.status(400).json({ NotFound: "Article Not Found" })
res.json({ article })
})
})
article schema
const schema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
title: { type: String, required: true },
image: { type: String, required: true },
content: { type: String, required: true },
email: { type: String, required: true },
author: { type: String, required: true, index: true },
added: { type: Date, default: Date.now },
pageview: { type: Number, default: 0 }
});
User schema
const schema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
username: { type: String, required: true },
email: { type: String, required: true },
facebookId: { type: String },
githubId: { type: String },
googleId: { type: String },
useravatar: { type: String, required: true },
userip: { type: String, required: true },
accessToken: { type: String },
date: { type: Date, default: Date.now }
});