I'm fairly new to nodejs and I'm doing a full stack developer challenge from devchallenges.io (Shoppingify). Below, I'm trying to add a new item. However, there's a slight delay between the return value from the request and the actual value in the database. The value updates straight away which is great however, the return value in the request is the previous value rather than being the current quantity value in the database.
// #route POST api/category
// #desc Add category and items
// #access Private
router.post(
'/',
[
check('name', 'Name is required').notEmpty(),
check('category', 'Category is required').notEmpty(),
],
auth,
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
errors: errors.array(),
});
}
const { name, note, image, category } = req.body;
const itemObject = { name, note, image, category };
try {
const categoryItem = await Category.find({
user: req.user.id,
});
// check if category object are empty
if (categoryItem.length === 0) {
const newCat = new Category({
user: req.user.id,
name: category,
items: itemObject,
});
await newCat.save();
res.json(categoryItem);
} else if (categoryItem.length !== 0) {
// check if category name already exists
categoryItem.map(async (cat) => {
if (cat.name.toLowerCase() === category.toLowerCase()) {
cat.items.push(itemObject);
await cat.save();
res.json(categoryItem);
} else {
// create new category
const newCat = new Category({
user: req.user.id,
name: category,
items: itemObject,
});
await newCat.save();
res.json(categoryItem);
}
});
}
} catch (error) {
console.error(error.message);
res.status(500).send('Server Error');
}
}
);
You are not returning the correct item…
Return the result of newcat.save()
Or try a new findById if newCat is not the correct object to return
Related
updateProfile: async function(req, res) {
try {
const update = req.body;
const id = req.params.id;
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('No files were uploaded.');
}
const image = req.files.profileImage;
const cloudFile = await upload(image.tempFilePath);
const profileImage = cloudFile.url
console.log('Loging cloudfile', profileImage)
await User.updateOne(id, { update }, { profileImage }, { new: true },
function(err, doc) {
if (err) {
console.log(err)
}
if (doc) {
return res.status(200).send({ sucess: true, msg: 'Profile updated successful' })
}
});
} catch (error) {
res.status(500).json({ msg: error.message });
}
}
But I'm getting an error of "Callback must be a function, got [object Object]"
I have tried to $set: update and $set: profileImage but still not working.
So the image successful upload into the cloudinary but the update for mongoose is not working.
Upon brief research into the issue, I think you are feeding the arguments in wrong. Objects can be confusing but not to worry.
Your code is:
await User.updateOne(id, { update }, { profileImage }, { new: true }
However, I believe it should be something more like:
await User.updateOne({id: id}, { profileImagine: profileImage, new: true },
The API reference annotates use of the function as:
const filter = { name: 'John Doe' };
const update = { age: 30 };
const oldDocument = await User.updateOne(filter, update);
oldDocument.n; // Number of documents matched
oldDocument.nModified; // Number of documents modified
I'm trying to update a sequelize model (called conversation) whenever I insert a value into its association (called message). The conversation model doesn't automatically update, and I haven't found any useful information in the docs.
const router = require("express").Router();
const { Conversation, Message } = require("../../db/models");
const onlineUsers = require("../../onlineUsers");
// expects {recipientId, text, conversationId } in body (conversationId will be null if no conversation exists yet)
router.post("/", async (req, res, next) => {
try {
if (!req.user) {
return res.sendStatus(401);
}
const senderId = req.user.id;
const { recipientId, text, conversationId, sender } = req.body;
// if we already know conversation id, we can save time and just add it to message and return
if (conversationId) {
const message = await Message.create({ senderId, text, conversationId });
Conversation.update({ })
return res.json({ message, sender });
}
// if we don't have conversation id, find a conversation to make sure it doesn't already exist
let conversation = await Conversation.findConversation(
senderId,
recipientId
);
if (!conversation) {
// create conversation
conversation = await Conversation.create({
user1Id: senderId,
user2Id: recipientId,
});
if (onlineUsers.includes(sender.id)) {
sender.online = true;
}
}
const message = await Message.create({
senderId,
text,
conversationId: conversation.id,
});
res.json({ message, sender });
}
catch (error) {
next(error);
}
});
module.exports = router;
for update you must change or append data into your record
and second argument is your condition for filter users (if you didnt pass argument for condition it means you didnt want to filter conversations then updade all of the records
await conversation.update(
{ title: 'sample title' },
{ where: { : 2 } }
)
I have a route that returns a particular story from an object Id. When i try testing it, it gives me some errors. The code inside if block is not executing somehow.
router.get("/:id",async (req,res) => {
try{
if (!isValidObjectId(req.params.userId)) {
res.status(401).json({
message: "Invalid object id",
success: false
})
throw new Error("Invalid object id")
}
let story = await Story.findById(req.params.id)
.populate('user')
.lean()
if (!story) {
return res.status(404).json({
message: "Story not found",
success: false
})
}
const text = convert(story.body, {
wordwrap: null
});
res.render('stories/show',{
story,
title: `${story.title} Storybooks`,
desc: `${text}`
})
}
catch(err) {
console.error(err)
}
})
I don't want to execute the query if the id is not valid say /stories/blabla
How can i do that?
Your response is appreciated.
For those of you struggling with the problem here is a time saver:
First we us the method isValid on mongoose.Types.ObjectId then as a 2nd check we create an actual object id an compare it as a string.
Here's how you would import and use it:
const mongoose = require('mongoose');
const {Types: {ObjectId}} = mongoose;
const validateObjectId = (id) => ObjectId.isValid(id) && (new ObjectId(id)).toString() === id; //true or false
As to answering my own question:
const mongoose = require('mongoose');
const {Types: {ObjectId}} = mongoose;
const validateObjectId = (id) => ObjectId.isValid(id) && (new
ObjectId(id)).toString() === id; //true or false
// #desc Show a single story
// #route GET /stories/:id
router.get("/:id",async (req,res) => {
try{
if (!validateObjectId(req.params.id)) {
throw Error("Invalid object Id")
}
let story = await Story.findById(req.params.id)
.populate('user')
.lean()
if (!story) {
return res.status(404).json({
message: "Story not found",
success: false
})
}
const text = convert(story.body, {
wordwrap: null
});
res.render('stories/show',{
story,
title: `${story.title} Storybooks`,
desc: `${text}`
})
}
catch(err) {
console.error(err)
}
})
EDIT:
I used req.params.userId instead of req.params.id so the above method is totally fine.
But just learnt a new way of doing it.
I'm trying out this code to create a simple order and then when trying to assign the user.shoppingCart Array to a new variable ("products") it says the user is undefined but for example the address is working just fine and then trying to console.log the user.address and user.shoppingCart it actually prints the correct values. Any ideas?
exports.createOrder = async (req, res) => {
try {
const user = await User.findById(req.user.id);
if (user.shoppingCart.length < 1) {
return res.status(400).json({
status: 'fail',
message: 'Please first add a product to your shopping cart.',
});
}
const address = req.body.address || user.address;
const products = user.shoppingCart;
const total = await getTotal();
const { paymentMethod } = req.body;
const order = await Order.create({
address,
user: user._id,
products,
total,
paymentMethod,
});
res.status(201).json({
status: 'success',
data: {
order,
},
});
} catch (err) {
res.status(500).json({
status: 'fail',
message: err.message,
});
}
};
I'm using bookshelf with mysql for my project and can't figure out how I can get the id when I'm creating a new record. Instead it just returns undefined.
// model.js
const User = bookshelf.model('User', {
tableName: 'user',
hidden: ['password']
});
// main.js
User.forge(attributes)
.save()
.then(function (newRow) {
console.log(newRow.id); // Should return the id
})
.catch(function (err) {
// Handle errors
});
newRow object contains fields only from attributes. To get row id we need to read this row from database.
Possibly this is a crutch, but I don't know a better solution.
const User = bookshelf.model('User', {
tableName: 'user',
hidden: ['password']
});
// main.js
User.forge(attributes)
.save()
.then(function (newRow) {
console.log(newRow.id); // undefined
User.where(attributes).fetch()
.then((createdUser) => {
console.log(createdUser); // any id (1 for example)
})
.catch(function (err) {
// Handle errors
});
})
.catch(function (err) {
// Handle errors
});
P.S Better to use javascript async/await syntax intead of Promise.then()/Promise.catch()
const User = bookshelf.model('User', {
tableName: 'user',
hidden: ['password']
});
// main.js (in a async function)
try {
const newRow = await User.forge(attributes).save();
console.log(newRow.id); // undefined
const createdUser = await User.where(attributes).fetch();
console.log(createdUser); // any id (1 for example)
} catch (err) {
// Handle errors
}
const User = bookshelf.model('User', {
tableName: 'user',
hidden: ['password']
});
// main.js
const user = await new User().save(attributes);
const {id} = user.toJSON()
or
const User = bookshelf.model('User', {
tableName: 'user',
hidden: ['password']
});
// main.js
User.forge(attributes)
.save()
.then(function (newRow) {
let {id} = newRow.toJSON();
console.log(id); // Should return the id
})
.catch(function (err) {
// Handle errors
});
The problem is that you are not calling toJSON to serialize.