Mongoose send requested to nested schema - javascript

I don't quite understand why my requests are not added to my DB. I have schema with nested objects. So I try to send requst to specific object inside of an object. Result says scucces, however nothing is added.
Here's schema:
const personSchema = new mongoose.Schema({
connections: {
parents: {type : Array},
children: {type : Array}
}
})
Here's router:
router.patch('/v2/:id', getPerson, async (req, res) => {
if (req.body.connections != null) {
if (req.body.connections.parents != null) { res.person.connections.parents.push(req.body.connections.parents); }
if (req.body.connections.children != null) { res.person.connections.children.push(req.body.connections.children); }
}
try {
const updatePerson = await res.person.save();
res.status(200).json({ message: 'Success' })
} catch (error) {
res.status(400).json({ message: error.message })
}
})
Here's middelware:
async function getPerson(req, res, next) {
let person;
try {
person = await Person.findById(req.params.id);
if (person === null) {
return res.status(404).json({ message: 'Cannot find the person' });
}
} catch (error) {
return res.status(500).json({ message: error.message });
}
res.person = person;
next();
}
Here's request:
PATCH http://localhost:3100/api-db/v2/62e28682cecc9120c7af9de5
Content-Type: application/json
{
"connections.parents" : "test"
}
Connection is established, document in db is alredy created.
It seems to me that I might doing wrong requst. I couldn't find information about nested requsts though.
What seems to be the problem?
P.S.
Other requsts that are not nested are satisfied...

Nvm, I am just retarded:
{
"connections" : {"parents" : "test"}
}

Related

Node Js: Remove string array element from mongoDB

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]" }})

Error in updating profile with image using mongoose and cloudinary

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

Why I still get the 200 response status code instead of 404?

I just making delete query to mysql with sequelize.
const model = require('../../../config/model/index');
const controller = {};
controller.drop = async function(req, res) {
try {
await model.activitys.destroy({
where: {
id: req.params.id
}
})
check_id = model.activitys.findAll({
where: {
id: req.params.id
}
})
if(check_id!=null){
res.status(200).json({
status: "Success",
message: "Success",
data: {}
})
}else{
res.status(404).json({
status: "Not Found",
message: `Activity with ID ${id} Not Found`,
data: {}
})
}
} catch (error) {
res.status(404).json({
status: "Error",
message: error.message
})
}
}
module.exports = controller;
I want to delete the data on DB from id parameters, it's work for deleting the data. But when I try to delete by id that not exist in my DB, it's still get the 200 status code.
How to make that will return 404 status code if there's no data exists in DB ?
If you want to check if a single record exists in DB then use findOne or findByPk instead of findAll. findAll always returns an array (either empty or not) and that means it's always not equal to null:
check_id = model.activitys.findOne({
where: {
id: req.params.id
}
})

Express + TSOA + Passport

I am new to Passport and to TSOA. I am trying to migrate an old Express route to TSOA controllers but I have not any idea how to achieve this. I did not find any documentation regarding this, in fact, I found this issue but I think I need a workaround.
router.post(
'/register',
(req: Request, res: Response, next) => {
const user: IUserData = req.body
if (validator.isEmpty(email))
return res.status(422)
.json({ error: 'Email is mandatory' })
if (validator.isEmpty(password.trim()))
return res.status(422)
.json({ error: 'Password is mandatory' })
next()
},
passport.authenticate('local'),
async (req: Request, res: Response) => {
if (req.user)
return res.json({ message: 'Already logged in' })
const existingUser: IUser = await UserModel.findOne({ email: req.body.email })
if (existingUser)
return res.status(400)
.json({ error: 'User exists' })
const data: IUserData = req.body
try {
const hashedPassword = await bcrypt.hashSync(data.password, parseInt(process.env.SALT_ROUNDS) || 10)
data.password = hashedPassword
} catch(error) {
return res.status(500)
.json({ error: error.message })
}
try {
const user: IUser = await new User(data)
await user.save()
res.json(user);
} catch(error) {
return res.status(500)
.json({ error: error.message });
}
return;
}
);
I have tried to "replicate" this code into a TSOA controller but I don't know how to apply the middleware stuff:
#Route('/auth')
export class AuthController extends Controller {
#Post()
public async register(#BodyProp() user: IUserData) {
const errors: Array<IAuthError> = []
if (validator.isEmpty(user.emailAddress)) {
this.setStatus(422)
return { error: 'Email is mandatory' }
}
if (validator.isEmpty(user.password.trim())) {
this.setStatus(422)
return { error: 'Password is mandatory' }
}
}
}
// to be continued ...
I could also separate this certain route in a different file (without any controller) but I don't know if that would work at all. I guess not.
How should I manage this?
Edit:
I just have read this article regarding TSOA authentication and it seems to handle authentication by using middlewares.

Nodejs and Mongoose data fetching

I have some problem with data fetching.
I have mongoose scheme.
PostSchema.methods.getAuthor = function () {
this.model('User').findById(this.author).exec(function (err, author){
if (author) {
console.log(author.username);
return author.username;
};
});
};
mongoose.model('Post', PostSchema);
and getMethod
exports.getPost = function (req, res) {
return Post.findById(req.params.id, function (err, post) {
if (!post) {
res.statusCode = 404;
return res.send({ error: 'Not found' });
}
if (!err) {
var author = post.getAuthor();
console.log('author is: ', author);
return res.send({ status: 'OK', post:post });
} else {
res.statusCode = 500;
return res.send({ error: 'Server error' });
}
});
};
When I call post.getAuthor() inside getPost method he is work and found User by Id. But var author = post.getAuthor(); have undefined value.
As #zaynetro mentioned you're calling your getAuthor method incorrectly. It's an asynchronous method, so you should be accepting a callback parameter, or you could return a promise.
But what you're trying to do is already built in to mongoose, its called query population.
http://mongoosejs.com/docs/populate.html
You can configure a Post.author reference property that you can have mongoose resolve into the document for you.
var postSchema = Schema({
author: {
type: Schema.Types.ObjectId,
ref: 'User'
}
});
mongoose.model('Post', postSchema);
var userSchma = Schema({
name: String
});
mongoose.model('User', userSchema);
Then, in your route your query would look like this:
Post
.findById(req.params.id)
.populate('author')
.exec(function(err, post) {
if (err) {
return res.status(500).send({
error: 'Server error'
});
}
// post.author contains the content of your author document
return res.send(post);
});

Categories

Resources