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.
Related
I have a user schema as follows:
const UserSchema = new mongoose.Schema({
skills: [String]
});
module.exports = mongoose.model("User", UserSchema);
And a Fetch request to delete a skill as follows:
const deleteItem = async (id) => {
try {
await fetch(`http://localhost:5000/api/user/deleteskill`, {
method: "DELETE",
headers: { "Content-Type": "application/JSON", token: accessToken },
body: JSON.stringify({ userid: userid , skill:id}),
})
.then((res) => res.json())
.then((data) => {
console.log("USER SKILLS:", data.userskills);
});
} catch (err) {
console.log(err);
}
};
Server
const deleteSkill = async (req, res) => {
try {
const user = await User.findById(req.body.userid)
//user.skills.pull(req.body.skill);
// removeskill = user.skills.filter(function(item) {
// return item !== req.body.skill
// })
if (user.skills.includes(req.body.skill)) {
res.status(400).json("Item Still Exists");
} else {
res.status(200).json("Item Deleted");
}
} catch (error) {
res.status(500).send({ error: error.message });
}
};
the array is in the following structure
[
'skill1', 'java', 'skill5'
]
I have tried to remove the user skill from the array in several ways but I still get res.status(400).json("Item Still Exists");. What I'm doing wrong?
Use the findOneAndUpdate method to find a document with the user id and update it in one atomic operation:
const deleteSkill = async (req, res) => {
try {
let message = "Item Deleted";
let status = 200;
const user = await User.findOneAndUpdate(
{ _id: req.body.userid },
{ $pull: { skills: req.body.skill } },
{ new: true }
)
if (user && user.skills.includes(req.body.skill)) {
message = "Item Still Exists";
status = 400;
} else if (!user) {
message = "User Not Found";
status = 404;
}
res.status(status).send({ message });
} catch (error) {
res.status(500).send({ error: error.message });
}
};
I believe you want to remove skills from the database then the following function could help you out.
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/";
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("mydb");
var myquery = { userid: userid, skillid: skillid};
dbo.collection("skills").deleteOne(myquery, function(err, obj) {
if (err) throw err;
console.log("1 document deleted");
db.close();
});
});
You have a method of removing elements from arrays, if you want to remove the first one you could use array.shift (more on it here), but if you want to delete it completely from your database you could always, find it and then update it.
User.update({ _id: userid }, { $pull: { "skills": "[skill]" }})
Basically what i am trying to do is-
getting comments and foreach comment getting its commentVote
getting the commentVote, checking if votes array inside each commentVote contains postedBy property or not also inlucdes loggedin
user id inside postedBy property
my controller -
exports.getComments = (req, res) => {
const { featureId } = req.params;
Comment.find({ feature: featureId })
.populate("postedBy", "_id username")
.sort({ createdAt: -1 })
.exec((err, comments) => {
if (err) {
return res.status(400).send({
error: errorHandler(err),
});
}
let commentsArray = comments;
commentsArray.forEach((comment) => {
CommentVote.findOne({ comment: comment._id }).exec(
(err, commentvote) => {
if (err) {
return res.status(400).send({
error: errorHandler(err),
});
}
console.log("commentvote.votes", commentvote.votes.length);
const votes = commentvote.votes;
const test = commentvote.votes.includes("req.auth._id");
console.log(test);
});
}
);
});
});
};
I am wondering if i can get true or false on console.log(test);
because based on that i will send response to that particular comment
That particular comment is liked or not!
How can I make a method in which if a user sign up that user get a 4 digit id? And that id increases whenever new user signup?
In NodeJS that id should be random but it should be at least 4 digit and it move on & on whenever a new user sign up but the minimum value should be 4 digit only so how can I built that method? if its a large process than please explain me I will get a idea or if its easy and it can be done in less lines of code than please provide snippets of that example you can check my code
user.controller:
const user_module = require('./user.modules');
class user_controller extends user_module {
static create_user = async (req, res) =>{
try {
console.log("controller response",req.body)
let response = await this.save_user_details(req)
let message = 'Success';
res.send({
sucess: true,
message: message,
data: response
})
} catch (error) {
let status_code = error.status.code != undefined ? error.status_code: 500;
let type = error.type != undefined ? err.type: 'Bad Request';
let message = err.custom_msg != undefined ? error.custom_msg: "Something went wrong"
res.status(status_code).send({
sucess: false,
error:type,
message: message
})
}
}
static get_users = async (req, res) =>{
try {
console.log("controller response",req.body)
let response = await this.retrieve_user(req)
let message = 'Success';
res.send({
sucess: true,
message: message,
data: response
})
} catch (error) {
let status_code = error.status.code != undefined ? error.status_code: 500;
let type = error.type != undefined ? err.type: 'Bad Request';
let message = err.custom_msg != undefined ? error.custom_msg: "Something went wrong"
res.status(status_code).send({
sucess: false,
error:type,
message: message
})
}
}
static otp_verify = async (req, res) =>{
try {
console.log("controller response",req.body)
let response = await this.verify_user(req)
if(response.status){
res.send({
success: true,
message: response.message,
data: response.user
})
}else{
res.status(400).send({
success: false,
error: false,
message: response.message
})
}
} catch (error) {
let status_code = error.status_code != undefined ? error.status_code: 500;
let type = error.type != undefined ? err.type: 'Bad Request';
let message = error.custom_msg != undefined ? error.custom_msg: "Something went wrong"
res.status(status_code).send({
sucess: false,
error:type,
message:message
})
res.end();
}
}
}
module.exports = user_controller
user.modules:
const models = require('../models');
class user_module {
static save_user_details = async (req) => {
try {
console.log("req body", req.body)
const { profileImage } = req.body
let set_data = req.body
if (!!profileImage) {
set_data.profileImage = profileImage
}
return await models.users.create(set_data)
} catch (error) {
throw error
}
}
static retrieve_user = async (req) => {
try {
let {limit, pagination} = req.query
let query = {}
let projection ={__v: 0}
let options = {
lean: true,
sort: {_id: -1},
skip: !Number(pagination) ? 0: Number(pagination) * !Number(limit) ? 10: Number(limit),
limit: !Number(limit) ? 10: Number(limit)
}
let users = await models.users.find(query, projection, options)
let count = await models.users.count(query)
return {users, count}
} catch (error) {
throw error
}
}
static verify_user = async (req) => {
try {
console.log("req body", req.body)
const { otp, user_id } = req.body
if(otp == '123456'){
let user = await models.users.findById(user_id)
return {user: user, status: true, message: 'success'}
}else{
return {user: null, status: false, message: 'Otp Invalid'}
}
} catch (error) {
throw error
}
}
}
module.exports = user_module
Schema:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Users = new Schema({
name: String,
phoneNumber: String,
userid: String,
profileImage: {
type: String,
default: 'https://www.pngitem.com/pimgs/m/146-1468479_my-profile-icon-blank-profile-picture-circle-hd.png'
},
about: String,
selectedCountry: {
type: Object
}
})
module.exports = mongoose.model("users", Users)
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
I am new to Node and Javascript in general and I was wondering if I should validate uniqueness by using FindOne before using .save.
My User schema does have Unique:true set for email and username and my current code works like a charm since mongoose returns an error message for uniques.
I wanted to know if it was better to validate for uniqueness before attempting to save for effiency or something?
Current code as follow :
export const createUser = (data) => {
return new Promise( async (resolve, reject) => {
const userData = JSON.parse(data);
const newUser = new User(userData);
await newUser.save((err) => {
if(err){
const msg = err.errmsg.toLowerCase();
const errormsg = msg.includes('email') ? 'Email already in use' : msg.includes('username') ? 'Username already in use' : 'Unexpected error.'
reject(JSON.stringify({error: errormsg}));
}
resolve(JSON.stringify({status: 200, created: true}));
});
});
};
Implemented here :
public register(req, res){
validateRegisterForm(req.body).then(data => {
createUser(data).then(resp => {
res.send(resp);
}).catch(err => {
res.send(err);
})
}).catch(err => {
res.send(err);
});
}