This question already has answers here:
Mongoose always returning an empty array NodeJS
(7 answers)
Closed 7 years ago.
Now I've played with nodeJS and SocketIO and all went fine.
But now I get caught at one query!
// User Auth Event
socket.on('userAuth', function(userObj) {
var queryUserAuth = User.find({
name : userObj.name
})
.where('password',userObj.pword);
queryUserAuth.exec(function(err, userData){
if(err) {
socket.emit('userAuthOK',err);
console.log('!! User: %s or PW not OK', userObj.name);
return handleError(err);
}else {
console.log('User: %s known, userID: %s', userObj.name, userData.userid);
socket.emit('userAuthOK', userData.userid);
socket.join(userData.userid); // Create new room / join this room
}
});
});
But all the time the var "userData" is empty and the console.log above tells me "User: testuser known, userID: undefined".
I can't get this user object from MongoDB this ways, but I can find the user if I take the mongo console.
///////////
EDIT:
After some changes... here the new code... but still without finding the right record and getting a result of null.
// User Auth Event
socket.on('userAuth', function(userObj) {
var queryUserAuth = User.findOne({
name : userObj.name,
password : userObj.pword
});
//.where("password").equals(userObj.pword);
queryUserAuth.exec(function(err, userData){
if(err) {
socket.emit('userAuthOK',err);
console.log('!! User Auth Error: %s', err);
return handleError(err);
}else {
if(!userData){
console.log('!! User: %s or PW not OK.', userObj.name);
socket.emit('userAuthOK','fail');
}else {
console.log('User: %s known, userID: %s', userObj.name, userData);
socket.emit('userAuthOK', userData);
socket.join(userData.userid); // Create new room / join this room
}
}
});
});
Here the output by manual query on mongo shell:
db.user.find({name: 'testuser', password: 'test'}) { "_id" : ObjectId("55a8cc8240fdc97f108d4d11"), "userid" : "1", "name" : "testuser", "email" : "test#test.com", "password" : "test" }
And this is the value of userObj: { name: 'testuser', pword: 'test' }
/////
EDIT2:
here the user.js including the mongoose model of User:
// Load the MongoDB module
var mongoose = require('mongoose');
// user schema
var userSchema = mongoose.Schema({
userid: Number,
name: String,
email: String,
password: String,
status: Number
});
// compiling the user schema
var User = mongoose.model('User', userSchema);
// make this available to our users in our Node applications
module.exports = User;
Here the include of the model:
// Load Mongoose models
var User = require('./models/user');
Try logging userData instead of just userData.userid. It's an Array, not an Object. You want to use .findOne(), not .find().
Also, the syntax for the query methods is:
.where("password").equals(userObj.pword)
Or, you could just add it to your original .findOne():
var queryUserAuth = User.findOne({
name: userObj.name,
password: userObj.pword
});
In addition, your console.log('!! User: %s or PW not OK', userObj.name); doesn't make any sense. Not finding anyone is different than getting an error. You'll want to handle that part as a separate if statement nested within the else block.
Related
I am having an admin portal in which I am handling all the collections that exist in my Mongo database. Now, I am building the update operations. I want to find a user that exist with his username and update the document with the changes that the admin performed.
For that reason, in my controller I have an endpoint which do the following:
exports.updateUser = async(req, res) => {
try{
var user = new User({
firstName: req.body.firstName,
lastName: req.body.lastName,
username:req.body.username,
password: req.body.password,
email: req.body.email
});
const static_username = req.body.static_username;
await User.findOneAndUpdate({static_username} , user, { useFindAndModify: false})
.then(data => {
if(!data){
res.status(404).send({ message : `Cannot Update user with ${id}. Maybe user not found!`})
}else{
res.redirect('/admin');
}
})
.catch(err =>{
res.status(500).send({ message : "Error Update user information"})
})
} catch {
console.log(err);
}
}
It takes the changes that the admin has made from the body and it puts them into user object. I also set to the variable static_username the username before update in order to find the user I to make the update.
I am getting a response that exist inside the catch of the query:
{ message : "Error Update user information"}
Error:
MongoServerError: Plan executor error during findAndModify :: caused by :: Performing an update on the path '_id' would modify the immutable field '_id'
Any thoughts why found user doesn't get updated?
You are sending a User object which has an _id field by default. So, unknowingly you are trying to modify the _id field and setting it to zero. To solve this, you can simply send a normal object.
var user = {
firstName: req.body.firstName,
lastName: req.body.lastName,
username:req.body.username,
password: req.body.password,
email: req.body.email
};
I think that the update input should contain only the fields you want to update. if username is the unique id in you User model, you would need to delete it from the user object - delete user.username - before passing it to findOneAndUpdate because an id cannot be updated. Also, as mentioned in the comments, try replacing the filter with { username: static_username}
Im trying to check if a token is unique before I use the save function, because I cannot create one from within.
I have tried to use the count, find and findOne functions, without any success...
exports.create_client = function(req, res){
token = crypto.randomBytes(8).toString('hex') + '-' + crypto.randomBytes(8).toString('hex') + '-' + crypto.randomBytes(8).toString('hex')
var client = new Client({
first_name: req.body.first_name,
last_name: req.body.last_name,
phone_number: req.body.phone_number,
pin_code: pincode_generator(6),
token: token
});
client.save(function(err, userClient){
if (err){
if(err.errors.phone_number)
res.status(400).send('Phone number is in use.');
if(err.errors.token)
res.status(400).send('Token is in use.');
} else {
res.status(201).send('User created successfully!')
}
});
};
Because of that the token is created in the server side it's the server's responsibility to give a unique token, and to prevent the error.
Before saving your data to Mongodb
you should while defining your schema with mongoose
set unique: true to the fields that you want to be saved as unique
var clientSchema = new Schema({
first_name: String,
last_name: String,
phone_number: {type: String , unique : true }
pin_code: String,
token: {type: String , unique : true }
});
and you should handle errors
So I resolved my issue by making an function object for the save function and call it from within it for saving again when I needed it.
You need to make sure that this value is unique in the DB as shown by rebai previously
client.save((err) => {
if (err) {
if (err.name === "MongoError" && err.code === 11000) {
if (err.keyPattern. phone_number) {
return res.status(422).send({
success: false,
error: "phone_number is already used" });
}
}
return res.status(422).send(err);
}
});
I am using MongoDB with Nodejs and I am trying to find the usertype value of a specific user so I've got this:
var myQuery= { username: req.body.username }, { "usertype": 1 };
dbo.collection("usercollection").find(myQuery, function(err, obj) { ...
What I need returned is the value of usertype from that specific user but it keeps saying I have a syntax error with : expected.
How can I fix this?
You have a syntax error since you're trying to define query and projection for find method in one line, try:
var myQuery= { username: req.body.username };
var options = { projection: { usertype: 1 } };
var cursor = dbo.collection("usercollection").find(myQuery, options)
I recommends to first perform the find operation to get the cursor and after it extract data from the cursor like below,
var myQuery= { username: req.body.username };
dbo.collection("usercollection").find(myQuery, { projection: { usertype: 1} }).toArray(function(err, result) {
if (err) throw err;
console.log(result);
});
In your case, the above code will work fine.
i'm new to mongodb and i'm having problems updating a local variable after a query. i'm using node js and i have a local variable i'm trying to update depending on my query result, but it seems that my functions returns before the query. i understand node js is asynchronous but i'm having trouble dealing with that. you can see my code below:
function userExist(userList, username){
//var usert = new UserSchema()
var exist = false
UserSchema.findOne({userName: username}, function (err, usert) {
if (err) return handleError(err);
if (usert) {
// doc may be null if no document matched
exist = true
}
})
console.log("boolean " + bool)
return exist
// return username in userList
// return query
}
I'm also having a different but unrelated issue where i'm trying to extract a specific value from a query result. my schema is as follow:
//import dependency
var mongoose = require('mongoose')
var Schema = mongoose.Schema
//create new instance of the mongoose.schema. the schema takes an
//object that shows the shape of your database entries.
var UserSchema = new Schema({
userName: String,
userID: String,
Conversations: [
{
conversationID: String,
messages: [
{
message: String,
messageID: String,
sender: String,
time: String
}
]
}
]
})
//export our module to use in server.js
module.exports = mongoose.model('User', UserSchema)
i'm trying to get the values in conversations array, add a new conversation to it and push it back in the database.
An answer to either question would be really helpful and appreciated.
just for clarification this is where i'm using the userExist function:
//Verify Username
socket.on(VERIFY_USER, (nickname, callback)=>{
if(userExist(connectedUsers, nickname)){
console.log("user exist")
callback({ userExist:true, user:null })
}else{
console.log("user does not exist")
callback({ userExist:false, user:createUser({name:nickname, socketId:socket.id})})
}
})
As already pointed out the findOne returns a promise.
You can handle the promise executing callbacks on the success or fail of the findOne result
Define two functions to pass as callbacks
function success(user){
//no error check
//doc has been found
//do something
} ;
function fail(err){
console. log(err)
}
Then in the findOne function body
if (err) return fail(err) ;
//else
return success(user)
OR
you can wrap the userExist function body to return a promise
function userExist(userList, username){
return new Promise(function(resolve, reject){
var exist = false
UserSchema.findOne({userName: username}, function (err, usert) {
if (err) return reject(err);
if (usert) {
// doc may be null if no document matched
exist = true
resolve(exist)
}
})
})
}
And when you call the userExist
userExist(userList, username).then(function(user){
//do something with the user
}).catch(function(reason) {
console.error(reason);
});
I'm currently working on a project using Node/Express/MongoDB. I'm using Mongoose to create my schema's and interface with DB. I'm using "express-sessions" module and have a session value set. Specifically, "req.session.user" which equals the username when logged in.
My question here, is how do I go about inserting the session value into mongodb? I have my model defined properly.
doc_type.model.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var TypesSchema = new Schema({
type_id: {
type: String,
uppercase: true,
required: true
},
type_description: {
type: String,
required: true
},
created_by: {
type: String,
required: false
},
creation_date: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('document_types', TypesSchema);
admin.js with routes defined.
adminRouter.route('/doc_types')
.get((req, res) => {
Type.find({}, (err, types) => {
if (err) {
console.error(err)
res.json(err)
}
else if (!req.session.user || !req.session.badge) {
res.redirect('/login');
}
else if (req.session.user || req.session.badge) {
res.render('doc_types', { pageTitle: 'Document Types', types: types, currentUser: req.session.user })
}
})
})
.post((req, res) => {
var type = new Type();
type.type_id = req.body.input_type_id;
type.type_description = req.body.input_type_description;
type.created_by = req.session.user;
type.save((err) => {
if (err) {
console.error(err)
res.json(err)
}
else {
res.json("Success!");
}
})
});
If you look under the .post method, you'll notice the line "type.created_by = req.session.user;". I then save my data into my db via schema. Upon doing so, my session value isn't passed into mongoose scheme. It's empty. However, when I console.log the req.session value, it displays fine there.
Can someone clarify my issue here? I'm stumped. It's probably something stupid I've overlooked.
Welp, it was something stupid. :) I was using postman to "POST" my data to the page. Postman has no idea what the session value was, therefore, no data sent to the mongoose document id. The session was only stored on the server/browser side. Lesson learned, haha.