doc.save() not working mongoose - node.js

I have a pretty basic user model in mongoose. It looks something like this.
var userSchema = new mongoose.Schema({
name: String,
email: String,
username: String,
message: {
active {type: Boolean, default: false},
text: String
}
});
When a user requests a certain page, I use findOne to get data for the user
UserModel.findOne({username: matchLowerCase(req.session.user)}, function (err, doc)
{
if (doc)
{
res.render('main', {
username: doc.username,
//etc
});
}
});
After the user loads the page, I want to set the "message" key to be inactive, like so.
doc.message = {
active: false,
text: ''
}
doc.markModified('message');
doc.save(function (err)
{
console.log('save err', err);
});
For whatever reason, doc.save() is not updating the message key. If I modify any other field in the script, doc.save() works. What am I missing?

Related

add username and password one table and other data in another using node js with rest api

I have one model is user in that model I was added email, username, password and name , when I have insert this data using node JS with the help of rest API, so that condition all 4 records are stored in one table
but I want email and name is stored in registration table and username and password stored in login table ,when I put login request using postman it with username name and password credentials it gives the successful response.
I am new to Node
My controller is
exports.user_signup = (req, res, next) => {
User.find({ username: req.body.username })
.exec()
.then(user => {
if (user.length >= 1) {
return res.status(409).json({
message: "Mail exists"
});
} else {
bcrypt.hash(req.body.password, 10, (err, hash) => {
if (err) {
return res.status(500).json({
error: err
});
} else {
const user = new User({
_id: new mongoose.Types.ObjectId(),
username: req.body.username,
password: hash,
email: req.body.email,
contact: req.body.contact,
});
user
.save()
.then(result => {
// console.log(result);
res.status(201).json({
message: "User created"
});
})
.catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
}
});
}
});
};
My Postman post method is in JSON form
{
"username":"tene",
"password":"tene",
"email":"tene#gmail.com",
"contact":1234567890
}
You can try this:
import mongoose from 'mongoose'
const { Schema } = mongoose
const userSchema = new Schema(
{
registrationTable : {
email: { type: String, required: true },
mobileNo: { type: String, required: true }
},
loginTable: {
username: { type: String, required: true },
password: { type: String, required: true }
}
},
{ timestamps: true }
)
const UserModel = mongoose.model('User', userSchema)
It will depend on you if you wanna make registration and login table as an object or array, but this will sure help.
required: true will be for, you need that value necessary, if you dont want some value just remove this.

Call a related collection via populate

I try to call a related list of logs for a certain user via Mongoose populate. Who can help me with finishing the response?
These are the schemes:
const logSchema = new Schema({
logTitle: String,
createdOn:
{ type: Date, 'default': Date.now },
postedBy: {
type: mongoose.Schema.Types.ObjectId, ref: 'User'}
});
const userSchema = new Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
}
logs: { type: mongoose.Schema.Types.ObjectId, ref: 'logs' }
});
mongoose.model('User', userSchema);
mongoose.model('logs', logSchema);
Inspired by the Mongoose documentary (see above) and other questions in relation to this subject I think I got pretty far in making a nice get. request for this user. I miss the expierence to 'translate it' to Express.
const userReadLogs = function (req, res) {
if (req.params && req.params.userid) {
User1
.findById(req.params.userid)
.populate('logs')
.exec((err, user) => {
if (!user) { }); // shortened
return;
} else if (err) {
return; // shortened
}
response = { //question
log: {
user: user.logs
}
};
res
.status(200)
.json(response);
});
} else { }); //
}
};
The response in Postman etc would be something like this:
{
"log": {5a57b2e6f633ce1148350e29: logTitle1,
6a57b2e6f633ce1148350e32: newsPaper44,
51757b2e6f633ce1148350e29: logTitle3
}
First off, logs will not be a list of logs; it will be an object. If you want multiple logs for each user, you will need to store is as an array: logs: [{ type: mongoose.Schema.Types.ObjectId, ref: 'logs' }]
From the Mongoose docs: "Populated paths are no longer set to their original _id , their value is replaced with the mongoose document returned from the database by performing a separate query before returning the results." In other words, in your query user.logs will be the logs document for each user. It will contain all the properties, in your case logTitle, createdOn, and postedBy.
Sending user.logs as json from the server is as easy as: res.json(user.logs). So your query can look like this:
const userReadLogs = function (req, res) {
if (req.params && req.params.userid) {
User1
.findById(req.params.userid)
.populate('logs')
.exec((err, user) => {
if (!user) { }); // shortened
return;
} else if (err) {
return; // shortened
}
res.status(200).json(user.logs)
});
} else { }); //
}
};
I hope this makes it a little bit clearer!

Why save() in mongoose is not a function?

I'm developing an app using Node.js, Mongoose, MongoDb, express.
I have 2 schemas one for student and one for snippets. I'm using the population model population model. I can create a user, and create a snippet and link it to the user. But I can't link and save the snippets in the user collection.
How to link and save the user so that it can have a reference to his snippets?
user and snippet schema
var userSchema = Schema({
name: { type: String, required: true, unique: true },
password: { type: String, required: true },
snippet: [{ type: Schema.Types.ObjectId, ref: 'Snippet' }]
})
var snippetSchema = Schema({
user: {type: Schema.Types.ObjectId, ref: 'User'},
title: String,
body: String,
createdAt: {
type: Date,
require: true,
default: Date.now
}
})
This is how I save the snippets I add it inside a user .save() function so that it saves the snippet ref but it gives me user.save() is not a function error.
var name = request.session.name.name
User.find({ name: name }).then(function (user) {
if (user) {
console.log('====================')
console.log(user)
user.save().then(function () { // problem is here?
var newSnippet = new Snippet({
user: user._id,
title: title,
body: snippet
})
newSnippet.save().then(function () {
// Successful
console.log('success')
response.redirect('/')
})
})
}
}).catch(function (error) {
console.log(error.message)
response.redirect('/')
})
But, I actually get the object printed after searching for it!
[ { _id: 5a2e60cf290a976333b19114,
name: 's',
password: '$2a$10$vD3EaQly4Sj5W3d42GcWeODuFhmHCSjfAJ1YTRMiYAcDBuMnPLfp6',
__v: 0,
snippets: [] } ]
You need to use User.findOne to get a valid user object, here you get an array. Also, don't forget to always return something in you promises (or throw an error).
Here is a quick rewrite of your function. With a few improvements such as arrow functions, const and a flat promise chain (never using any .then inside another .then) and avoiding code repetition
const name = request.session.name.name
User.findOne({ name })
.then(user => {
if (user) return user.save()
// What to do if not found? Throw an error?
throw new Error('User not found')
})
.then(() => {
const newSnippet = new Snippet({
user: user._id,
title: title,
body: snippet,
})
return newSnippet.save()
})
.catch((error) => console.log(error.message))
.then(() => response.redirect('/'))

Mongoose - multiple parameters in findOne

Here is a route I have:
router.get('/home', function (req, res) {
User.findOne({_id: req.user._id}, function (err, user) {
if (err) return next(err);
res.render('home', {user: user});
});
});
Basically, in order for someone to view this /home page they need to be logged in, which is where User.findOne comes into play. It will search for the user in the 'user' collection; if it doesn't find the user (if the user isn't logged in), it will return an error. Otherwise, it will show them the /home page.
Now, I want to have a separate Admin section of my website where only users with admin privileges can access the page. I've tried doing something like this:
router.get('/admin', function (req, res) {
User.findOne({_id: req.user._id, admin: true}, function (err, user) {
if (err) return next(err);
res.render('admin', {user: user});
});
});
What I'm trying to get the code to do is to look for 2 parameters: whether the user is logged in, and whether or not in that user document their 'admin' is set to 'true'. Obviously the above code doesn't work, and I don't know how to get this to work better.
EDIT: my user schema:
var schema = mongoose.Schema;
var UserSchema = new schema ({
username: {type: String, unique: true},
email: {type: String, unique: true, lowercase: true, required: true},
password: {type: String, minlength: passMinLength, required: true},
admin: {type: Boolean, default: false},
profile: {
firstName: {type: String, default: ''},
lastName: {type: String, default: ''}
}
});
there is nothing wrong in the query {_id: req.user._id, admin: true} , and it should work if User.Schema contains the admin(Boolean) field also.
Besides, alternate way is to check for admin once you get the User object.
User.findOne({_id: req.user._id}, function (err, user) {
if (err) return next(err);
if(!user){
//considering admin is boolean field
if(!user.admin){
// Not Authorised to access, do something
}
else{
// User verified as Admin
res.render('admin', {user: user});
}
}
// UserId Not found, do something
});

Express - Save not being called

He there,
I just started using express / mongoose and I'm new with the concept. Currently trying to update a counter each time a user logges in. I'm using expres 4.8.8, mongoose, 3.8.15, passport 0.2.1
I have the following route, the function is being called on success:
// Set up the 'signin' routes
app.route('/signin')
.get(users.renderSignin)
.post(passport.authenticate('local', {
failureRedirect: '/',
failureFlash: true
}),function(req,res,next){
users.updateLoginCount(req.user.id);
res.redirect('/');
});
Then in the user controller, I want to update the login counter of the user that is currently logging in:
exports.updateLoginCount = function(user_id){
User.findById(user_id, function(err,user){
if(!err){
user.counters.login += 1;
user.save(function(err){
console.log('start save');
if(err) {
console.log(err);
}else{
console.log(user.username + ' logged in for the ' + user.counters.login + ' time');
}
});
}else{
console.log('Error');
}
});
};
Model looks something like:
// Define a new 'UserSchema'
var UserSchema = new Schema({
firstName: String,
lastName: String,
email: {
type: String,
// Validate the email format
match: [/.+\#.+\..+/, "Please fill a valid email address"]
},
username: {
type: String,
// Set a unique 'username' index
unique: true,
// Validate 'username' value existance
required: 'Username is required',
// Trim the 'username' field
trim: true
},
password: {
type: String,
// Validate the 'password' value length
validate: [
function(password) {
return password && password.length > 6;
}, 'Password should be longer'
]
},
salt: {
type: String
},
provider: {
type: String,
// Validate 'provider' value existance
required: 'Provider is required'
},
providerId: String,
providerData: {},
created: {
type: Date,
// Create a default 'created' value
default: Date.now
},
counters:{
login:{
type:Number,
default: 0,
}
}
});
But somehow it doesn't call the user.save(). It also doesn't show any errors, so I have no idea what I'm doing wrong here. It works fine till the user.save() part.
I hope that someone can point out the mistake I'm making. If there is more information needed, please let me know!
Since the node.js is asynchronus I believe that your res.redirect executed before the login update function finishes executing. So, you need to set a callback for your method and run the res.redirect after your update is completed.
You can use mongoose update statement to increase a value like below by the way. Of course go on with the findById if you need other user info.
exports.updateLoginCount = function(user_id, callback){
User.update('_id' : user_id, {$inc: {"counters.login" : 1}}, function(err){
if(err)
console.log(err);
else{
console.log(user_id + " login count increased by one" );
callback();
}
});
}
Calling the method;
...
}),function(req,res,next){
users.updateLoginCount(req.user.id, function(){
res.redirect('/');
});
});
PS: I don't have a chance to test it now though, probably includes some syntax errors :)

Resources