I'm stuck saving a object with an array of object Id. I'm using node.js with restify and mongoose.
I have an outfit-request with many outfit-choices:
Model:
const outfitRequestsSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
title: {
type: String
},
maxCost: {
type: Number
},
outfitChoices: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'OutfitChoice'
}]
}, {usePushEach: true});
Router:
application.post('/outfit-choices', (req, resp, next) => {
OutfitRequest.findById(req.body.outfitRequest)
.then(outfitRequest => {
console.log(outfitRequest);
const outfitChoice = new OutfitChoice(req.body);
outfitChoice.save().then(outfitChoice => {
outfitRequest.outfitChoices.push(outfitChoice._id);
outfitRequest.save()
.then(outfitRequestNew => {
console.log(outfitRequestNew);
this.render(resp, next);
})
.catch(next);
}).catch(next);
})
.catch(next);
});
Render method:
render(response: restify.Response, next: restify.Next) {
return (document) => {
if (document) {
this.emit('beforeRender', document);
response.json(document);
} else {
response.send(404);
}
return next();
}
}
Restlet screen
It keeps in a loop, but the record is saved in the db
DB screen
I think that is a problem with chained promises, but I can't find out how to solve this.
I got it like this, I returned the last promise and put the print in a .then
application.post('/outfit-choices', (req, resp, next) => {
OutfitRequest.findById(req.body.outfitRequest)
.then(outfitRequest => {
const outfitChoice = new OutfitChoice(req.body);
outfitChoice.save()
.then(outfitChoice => {
outfitRequest.outfitChoices.push(outfitChoice._id);
return outfitRequest.save()
})
.then(this.render(resp, next))
.catch(next);
})
.catch(next);
});
Related
I want to update data in the server with a Axios Patch call and there seems to be some error in the code which i cant seem to figure out. Help me out please.
Node express API call in the backend:
router.patch('/up',async (req, res) => {
try{
const id = req.query.userid; // User objectid here.
console.log(req.body)
console.log(req.query.userid)
const result= User.findById(id, (error, foundUser) => {
if (foundUser) {
const { products } = foundUser;
const filteredproducts = products.filter((item) => {
return item._id!= req.body.body._id; //product array object id
});
while (foundUser.products.length > 0) {
foundUser.products.pop();
}
foundUser.products = filteredproducts;
foundUser.products.push({
brandname: req.body.brandname,
productname: req.body.productname,
quantity: req.body.quantity,
price: req.body.price,
description: req.body.description
});
foundUser.save();
}
else
{
console.log('User not found')
}
})
res.status(200).send("update successfull");
}
catch(err){
res.status(403).send('update unsuccessfull')
console.log(err)
}
})
Userschema in db:
const userschema = new mongoose.Schema({
username: {
type: String,
},
email: {
type: String,
required: true
},
place: {
type: String,
required: true
},
password: {
type: String,
required: true
},
products:[
{
brandname: {
type:String,
required:true
},
productname:{
type:String,
required:true
},
quantity:{
type:Number,
required:true
},
price:{
type:Number,
required:true
},
description:{
type:String,
required:true
}
}
]
,
tokens:
[{
token: {
type: String,
required: true
}
}
]
})
const User = mongoose.model('USER', userschema)
Front end API code
const updateproduct = async(req,res) => {
console.warn(values.brandname, values.productname,values.quantity, values.price,
values.description)
console.warn("userlogin is:,",userid) // User object id here.
const _id=id; // Product object id here
await axios.patch(`http://localhost:5000/up`,{
headers: {
'Content-type': 'application/json'
},
data: {brandname,productname,quantity,price,description,_id}, //getting the values of all the fields here. checked by console logging them.
params:{
'userid':userid
}
},
{ withCredentials: true })
.then((res) => {
console.log(res)
navigate('/listproduct')
})
.catch((err) => {
console.log(err)
})
}
Sorry if my code look really bad. I am new to React and node.
All i wanna do is edit the product details of a product by the product objectid and store it in the db.
Any other method other than this is also fine. I am stuck with this problem for more than 2 days coudn't find a solution till now. Any help is much Appreciated.
EDIT:
I have tried to update the code but still the same errors.
backend API
router.patch('/up',async (req, res) => {
try{
const id = req.query.userid;
console.log("user id is",id)
console.log("req.body",req.body.body.brandname)
const result= User.findById(id, (error, foundUser) => {
if (foundUser) {
const { products } = foundUser;
const filteredexpenses = products.filter((item) => {
return item._id!= req.body.body._id;
});
while (foundUser.products.length > 0) {
foundUser.products.pop();
}
foundUser.products = filteredexpenses;
foundUser.products.push({
brandname: req.body.body.brandname,
productname: req.body.body.productname,
quantity: req.body.body.quantity,
price: req.body.body.price,
description: req.body.body.description
});
foundUser.save();
}
else
{
console.log('User not found')
}
})
res.status(200).send("update successfull");
}
catch(err){
res.status(403).send('update unsuccessfull')
console.log(err)
}
})
Front end API
const updateproduct = async(req,res) => {
console.warn(values.brandname, values.productname,values.quantity, values.price, values.description)
console.warn("userlogin is:,",userid)
const _id=id;
await axios.patch(`http://localhost:5000/up`,{
headers: {
'Content-type': 'application/json'
},
body:
{'brandname':brandname,'productname':productname,'quantity':quantity,'price':price,'description':description,'_id':_id},
params:{
'userid':userid
}
},
{ withCredentials: true })
.then((res) => {
console.log(res)
navigate('/listproduct')
})
.catch((err) => {
console.log(err)
})
}
Result on console log is
User id is undefined
req.body adidas //brandname
User not found
Try to change your axios request passing all parameters in the body like this:
await axios
.patch(
`http://localhost:5000/up`,
{ brandname, productname, quantity, price, description, _id, userid },
{
headers: {
'Content-type': 'application/json',
},
},
{ withCredentials: true }
)
.then((res) => {
console.log(res);
navigate('/listproduct');
})
.catch((err) => {
console.log(err);
});
And handle the end point like this:
router.patch('/up', async (req, res) => {
try {
const id = req.body.userid;
User.findById(id, async (error, foundUser) => {
if (foundUser) {
const { products } = foundUser;
const { brandname, productname, quantity, price, description, _id } =
req.body;
const filteredexpenses = products.filter((item) => {
return item._id != _id;
});
while (foundUser.products.length > 0) {
foundUser.products.pop();
}
foundUser.products = filteredexpenses;
foundUser.products.push({
brandname,
productname,
quantity,
price,
description,
});
await foundUser.save();
res.status(200).send('update successfull');
} else {
console.log('User not found');
res.status(400).send('User not found');
}
});
} catch (err) {
res.status(403).send('update unsuccessfull');
console.log(err);
}
});
I am trying to create a followers/following function in my project. However I cannot seem to update the DB correctly. I'm able to send the ids as they both print when I console.log but nothing in my DB updates and I do not get any response in my frontend.
route
app.put('/api/follow', async function (req, res, next){
const { id } = req.query;
const userFrom = req.body.data
console.log('OTHER USER ID',id)
console.log('CURRENT ID', userFrom)
User.findByIdAndUpdate(id), {
$push:{followers:req.body.data}
},{new:true},
(err,result)=>{
if(err) {
if(err) return res.status(400).send(err)
}
User.findByIdAndUpdate(req.body.data), {
$push:{following:id}
},{new:true}.then(result=> {
res.json(result)
}).catch(err=>{
return res.status(422).json({error:err})
})
}
})
user model
const mongoose = require("mongoose");
const User = mongoose.model(
"User",
new mongoose.Schema({
username: String,
email: String,
password: String,
phoneNo: String,
bio: String,
filePath: String,
following: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
followers: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
})
);
module.exports = User;
my route end function
const clickHandler = () => {
const currentID = currentUser.id;
const id = this.props.id;
console.log('CURRENT ID',currentID)
console.log('otherUserID',id)
Axios.put(`http://localhost:8080/api/follow/?id=${id}`, { data: currentID }, { headers: authHeader() })
.then(response => {
if (response.data.success) {
console.log('FOLLOWED', response.data)
// this.setState({ userDetails: response.data.details })
} else {
alert('Error')
}
})
}
This should be
User.findByIdAndUpdate(id, {
You should not close the bracket after id but after new: true})
I'm working on a twitter clone to learn MERN stack, here's a new tweet route
router.route('/new')
.post( (req, res) => {
const { errors, isValid } = validateTweet(req.body);
if (!isValid) {
return res.status(400).json(errors);
}
let tweet = new Tweet({
content: req.body.content,
created_by: req.user.id
})
User.findById(req.user.id, (err, user) => {
if (err) return res.status(400).json(err)
user.tweets.push(tweet._id);
user.save();
});
tweet.save();
return res.status(201).json(tweet);
});
Which does not return timestamps for the tweet, how can i achieve this without querying the database for the tweet before returning it?
Here's the model just in case:
const tweetSchema = new Schema({
content: {
type: String,
required: true,
minlength: 1,
maxlength: 128,
trim: true
},
created_by: {
type: Schema.Types.ObjectId, ref: 'User',
required: true
}
}, {
timestamps: true
});
const Tweet = mongoose.model('Tweet', tweetSchema);
What i ended up doing was making the funcion async then returning the result of the fulfilled save(). Not sure if this is a good practice or not.
router.route('/new')
.post( async (req, res) => {
const { errors, isValid } = validateTweet(req.body);
if (!isValid) {
return res.status(400).json(errors);
}
let tweet = new Tweet({
content: req.body.content,
created_by: req.user.id
})
User.findById(req.user.id, (err, user) => {
if (err) return res.status(400).json(err)
user.tweets.push(tweet._id);
user.save();
});
tweet = await tweet.save();
return res.status(201).json(tweet);
});
I have created a Mongo DB schema with Mongoose in Express.js and I am building the REST API. However when I try to update existing records the values that I do not update from the schema automatically become null. I understand why this happens just not sure exactly how it should be coded.
This is the route:
router.patch("/:projectId", async (req, res) => {
try {
const updatedProject = await Project.updateOne(
{ _id: req.params.projectId },
{
$set: {
title: req.body.title,
project_alias: req.body.project_alias,
description: req.body.description
}
}
);
res.json(updatedProject);
} catch (err) {
res.json({ message: err });
}
});
also here is the schema:
const ProjectsSchema = mongoose.Schema({
title: {
type: String,
required: true,
unique: true
},
project_alias: {
type: String,
unique: true,
required: true
},
description: String,
allowed_hours: Number,
hours_recorded: {
type: Number,
default: 0
},
date_added: {
type: Date,
default: Date.now
}
});
My problem is that when I want to update just the title:
{
"title" : "Title Updated33"
}
description and alias become null. Should I implement a check?
Just use req.body for the update object like this:
router.patch("/:projectId", async (req, res) => {
try {
const updatedProject = await Project.updateOne(
{ _id: req.params.projectId },
req.body
);
res.json(updatedProject);
} catch (err) {
res.json({ message: err });
}
});
Or even better, create a helper function like this so that we can exclude the fields in the body that doesn't exist in the model:
const filterObj = (obj, ...allowedFields) => {
const newObj = {};
Object.keys(obj).forEach(el => {
if (allowedFields.includes(el)) newObj[el] = obj[el];
});
return newObj;
};
router.patch("/:projectId", async (req, res) => {
const filteredBody = filterObj(
req.body,
"title",
"project_alias",
"description",
"allowed_hours",
"hours_recorded"
);
try {
const updatedProject = await Project.updateOne(
{ _id: req.params.projectId },
filteredBody
);
res.json(updatedProject);
} catch (err) {
res.json({ message: err });
}
});
I working on Mongoose and Express project where by I have 3 models: User, Album and Purchase. The purchase model references the user and album. I am creating a POST endpoint where by I can make a purchase and then retrieve the data as well as the user and album relations which should be populated with their data, but I am stuck.
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var userSchema = mongoose.Schema({
// TODO: Define Schema
name: {
type: String,
required: true
}
})
var User = mongoose.model('User', userSchema)
var albumSchema = mongoose.Schema({
// TODO: Define Schema
title: {
type: String,
required: true
},
performer: {
type: String,
required: true
},
cost: {
type: Number,
required: true
}
})
var Album = mongoose.model('Album', albumSchema);
var puchaseSchema = mongoose.Schema({
// TODO: Define Schema
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Album'
},
album: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
}
})
var Purchase = mongoose.model('Purchase', puchaseSchema);
app.use(bodyParser.json());
app.listen(3000);
// TODO: GET /albums
app.get('/albums', (req,res) => {
Album.find()
.then((response) => {
res.json({data: response})
})
.catch(err => {
res.json({error: err})
})
})
// TODO: GET /albums/:id
app.get('/albums/:id', (req,res) => {
Album.findById(req.params.id)
.then(response => {
res.json({data: response})
.catch(err => {
res.json({Error: err})
})
})
})
// TODO: POST /albums
app.post('/albums', (req,res) => {
const newPost = Album({
title: req.body.title,
performer: req.body.performer,
cost: req.body.cost
})
newPost.save(err => {
if(err)
res.json({error: err})
})
.then(data => {
res.json({data: data})
})
})
// TODO: PUT /albums/:id
app.put('/albums/:id', (req,res) => {
Album.findByIdAndUpdate(req.params.id, req.body, {new: true},
(err, album) =>{
if(err) return res.status(500).send(err)
return res.json({data: album})
})
})
// TODO: DELETE /albums/:id
app.delete('/albums/:id', (req,res) => {
const id = req.params.id
Album.findById(id)
.then(docs => {
docs.remove()
res.status(204)
.json({data:docs})
})
})
// TODO: POST /purchases
app.post('/purchases', (req,res) => {
})```
This might help you. Look into mongoose's populate method.
app.post('/purchases', (req,res) => {
const user = req.body.userId;
const album = req.body.albumId;
const newPurchase = new Purchase({
user: user,
album: album
});
newPurchase.save().then((purchase) => {
Purchase.findById(purchase.id).populate('user').populate('album').then((purchaseData) => {
return res.json({purchaseData});
}).catch(e => {
console.log(e);
});
}).catch(e => {
console.log(e);
});
})
Here's an alternative for populating after saving the document.
app.post('/purchases', (req,res) => {
const user = req.body.userId;
const album = req.body.albumId;
const newPurchase = new Purchase({
user: user,
album: album
});
newPurchase.save().then((purchase) => {
Purchase.populate(purchase, [{path: 'user'}, {path: 'album'}], (err, data) => {
if(err) {
return res.json(e);
}
return res.json(data);
});
}).catch(e => {
console.log(e);
});
}
)
As mentioned here: https://mongoosejs.com/docs/api.html#model_Model.populate