i want to find a specific record in mongoose. i'm trying to make a login/register form and im kind of new to node.js..
for now i have this code:
app.post('/register', function(request, response)
{
console.log('REGISTER OK');
//set connection to mongodb.
mongoose.connect('mongodb://localhost');
var db = mongoose.connection;
//Connect to mongodb.
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback()
{
console.log('connection succeed.');
//Create User schema.
var userSchema = mongoose.Schema(
{
username: String,
password: String
});
//User model.
var UserModel = mongoose.model('User', userSchema);
var user = new UserModel(
{
username: request.body.username,
password: request.body.password
});
user.save(function(error, data)
{
if(error)
console.log(error);
else
{
response.render('register',
{
'Title': Title,
'result': data
});
UserModel.find(function(error, data)
{
if(error)
console.log(error);
else
console.log(data);
});
}
});
});
});
i dont quite get the find method of mongoose, i just need to find the username in order to do some function, is there a function that moongose has to avoid record if this exists already?
UserModel.findOne ({ name: "someName" }, function (err, user) {
if (err) console.log (err);
if (!user) console.log ('user not found');
// do something with user
});
Related
It has show "Database connected" , I think database has already connected to mongodb server already. However ,there has nothing to be console log. Data is null here and nothing is print on my page.
Here is my code.
index.js
var userModel = require('../models/userModel.js');
router.get('/', function (req, res, next) {
mongoose.connect('mongodb://localhost:27017/db', { useNewUrlParser: true }, function (err) {
if (err) console.log("connect fail");
console.log("Database connected");
});
})
userModel.find({}, function (err, data) {
if (err) {
return console.log(err)
}
console.log(data);
res.render('index', {
title: 'Account', user: data, loginStatus: isLogin
});
})
models/userModel.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.Promise = global.Promise;
var userSchema = new mongoose.Schema({
name: String,
account: String,
password: String,
email: String
});
var model = mongoose.model('user', userSchema);
module.exports = model;
The problem in this is you're connecting database on api call which should never be the case. You should always do it in the beginning and call the collections at the endpoints. Now whenever you'll call '/' check server console.
var userModel = require('../models/userModel.js');
mongoose.connect('mongodb://localhost:27017/db', { useNewUrlParser: true }, function (err) {
if (err) console.log("connect fail");
console.log("Database connected");
});
router.get('/', function (req, res, next) {
userModel.find({}, function (err, data) {
if (err) {
return console.log(err)
}
console.log(data);
res.render('index', {
title: 'Account', user: data, loginStatus: isLogin
});
})
})
I have a problem to update user if his/her name is not available in my database
I thought if my function "User.findOne" doesn't find a user in my mongodb it can update database. Unfortunately nothing happens. I get only output "Hello Anna you are new here!" My name is not saved into my mongodb
Could somebody smart give me please a tip how can I save username if it is not in my database
var User = require('./user');
var myName = this.event.request.intent.slots.first_name.value;
self = this;
User.findOne({ name: myName }, function(err, user) {
if (err ||!user){
var userSave = new User({
name: myName
});
userSave.save(function (err, results) {
console.log(results);
self.emit(':ask',
"Hello "+ myName +"you are new here!")
});
}
else {
self.emit(':ask',
"Hello "+ myName +" you are not new!")
}
});
My mongoose model code:
//user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
mongoose.connect("mongodb://c******mlab.com:***/users");
var userSchema = new Schema({
name: String,
userId: { type: String, required: false, unique: true }
});
var User = mongoose.model('User', userSchema);
module.exports = User;
var User = require('./user');
var myName = this.event.request.intent.slots.first_name.value;
self = this;
User.findOne({
name: myName
}, (err, user) => {
if(err) throw err;
if(user) {
self.emit(':ask', `Hello ${myName} you are not new`);
} else {
User.create({
name: myName
}, (err, result) => {
if(err) throw err;
console.log(result);
self.emit(':ask', `Hello ${myName} you are new here!`);
})
}
});
this should work.
The line if (err || !user) is confusing to read, and in this style you're mixing error handling (if (err)) and a condition in your code that you expect to hit (if (!user)). I suggest you separate them so the code is easier to read and debug.
For example, using plain Javascript and the MongoDB node driver:
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect('mongodb://localhost/test', function(err, conn) {
// connection error handling
if (err) {
console.log('Connection error: ' + err);
}
conn.db('test').collection('test').findOne({name:'abc'}, function(err, doc) {
// findOne error handling
if (err) {
console.log('Error: ' + err);
}
// if document exists
if (doc) {
console.log('Document found: ' + JSON.stringify(doc));
}
// if document doesn't exist
else {
console.log('Document not found');
}
conn.close();
});
});
If the database contains the user abc, the output would be:
$ node script.js
Document not found
If the user abc exists:
$ node script.js
Document found: {"_id":0,"name":"abc"}
I believe using a similar pattern you can modify your code to do what you need.
I have a problem with Schema.pre('save'), in my model 'user', cannot get 'this' for the hashed of my password with bcrypt.
my app.js, Simple connect in mongodb using mongoose
mongoose.connect('mongodb://localhost/gederson', {
useMongoClient: true,
});
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', () => {
console.log('Connected on mongo');
});
app.listen(process.env.PORT || 3000, () => {
console.log('listening');
});
index(app, db);
post(app, db);
admin(app, db);
module.exports = app;
my route, I created the route for create user in my application, but in pre 'save' cannot get the 'this' for hash password.
const Users = db.model('Users');
const newUser = {
username: req.body.username,
email: req.body.email,
password: req.body.password,
};
Users.create(newUser, (err) => {
if (err) throw err;
res.status = 201;
return res.send('User created');
});
my model user, the code pre 'save'
const bcrypt = require('bcrypt');
UserSchema.pre('save', (next) => {
const user = this;
bcrypt.hash(user.password, 10, (err, hash) => {
if (err) {
return next(err);
}
user.password = hash;
return next();
});
});
const Users = mongoose.model('Users', UserSchema);
module.exports = Users;
Stack Error:
events.js:183
throw er; // Unhandled 'error' event
^
Error: data and salt arguments required
at /home/gedersonchiquesi/ProjetosDev/wos/node_modules/bcrypt/bcrypt.js:114:16
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
[nodemon] app crashed - waiting for file changes before starting...
I ran into a similar issue today.
I resolved the matter by removing the ES6 syntax (arrow function).
UserSchema.pre('save', function(next) {
const user = this;
bcrypt.hash(user.password, 10, function(err, hash) {
if (err) {
return next(err);
}
user.password = hash;
next();
})
});
because you are passing the blank value of the inputs on that function
if test on postman or else data input needed
{
"name":"test",
"email":"test#test.com",
"password":"123456"
}
add see my code example for datastore
router.post("/register-user", (req, res, next) => {
bcrypt.hash(req.body.password, 10).then((hash) => {
const user = new userSchema({
name: req.body.name,
email: req.body.email,
password: hash
});
user.save().then((response) => {
res.status(201).json({
message: "User successfully created!",
result: response
});
}).catch(error => {
res.status(500).json({
error: error
});
});
});
});
My issue was my server wasn't accepting the correct data type.
Had to include the following on server.js file:
app.use(express.json()); &
app.use(express.urlencoded({extended: true}));
I am trying to save my model into the my db in MongoDB. This code actually works if I were to go through this code path when running the node server, however when I try to use mocha to test saving the model it doesn't get saved anymore. I have verified that the connection to mongodb is fine. Thia is the output:
before regular save
after regular save
Any tips or suggestions would be greatly appreciated. thanks!
This is the test I am running.
var app = require('./helpers/app');
var User = require('../models/user');
var supertest = require('supertest');
var should = require('should');
var mongoose = require('mongoose');
var MongoUrl = require('./../config.js').mongoUri
var clearDB = require('mocha-mongoose')(MongoUrl);
var testuser = {
username:"admin1",
password:"password",
email:"test#gmail.com",
firstname:"testfirst",
lastname:"testlast",
phonenumber:"4151231234"
};
describe("Routing", function() {
describe("Creating an account", function() {
//To run before each test. DB Clean up is implicitly done after each test.
beforeEach(function(done) {
if (mongoose.connection.db) {
return done();
}
mongoose.connect(dbURI, done);
});
it('User: Creating an account2', function(done){
var newUser = new User({
username: "testusername",
email: "test1#gmail.com",
password: "password",
phoneNumber: "12312312",
firstname: "testfirst",
lastname: "testlast"
});
console.log("before regular save");
newUser.save(function(err){
if(err){
console.log("testerror: " + err);
}
console.log("in regular save");
});
console.log("after regular save");
User.find({}, function(err, docs){
if (err) return done(err);
console.log(docs);
docs.length.should.equal(1);
done();
});
});
});
});
Model#save is an async function so you have to wait until it calls its callback before you can expect to be able to find the saved doc with a Model.find call.
So put the find check inside the save callback:
it('User: Creating an account2', function(done){
var newUser = new User({
username: "testusername",
email: "test1#gmail.com",
password: "password",
phoneNumber: "12312312",
firstname: "testfirst",
lastname: "testlast"
});
console.log("before regular save");
newUser.save(function(err){
if(err){
console.log("testerror: " + err);
return done(err);
}
console.log("in regular save");
console.log("after regular save");
User.find({}, function(err, docs){
if (err) return done(err);
console.log(docs);
docs.length.should.equal(1);
done();
});
});
});
Why could the example below be returning the node middle-ware function before my mongoose db lookup function finishes? I am sure this is a async issue but I am a bit lost on why.
Middle-ware js file
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
function isUser(login){
var UsersSchema = new Schema({
user: String,
user_type: String,
password: String,
first_name: String,
middle_name:String,
last_name: String,
birth_date: Date,
join_date: Date
});
var UserModel = mongoose.model('users', UsersSchema);
mongoose.connect('mongodb://localhost/identity');
mongoose.model('users', UsersSchema);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error: '));
db.once('open', function cb () {
UserModel.findOne({'user': login}, function (err, user){
if (err){ throw err; }
console.log('connected to user db and preformed lookup.');
console.log(user);
return user;
});
});
}
module.exports.authenticate = function (login, password, cb) {
var user = isUser(login),
msg;
console.log(user);
if (!user) {
msg = 'Invalid User';
cb(null, msg);
return;
}
if (user.password != password) {
msg = 'Invalid Password';
cb(null, msg);
return;
}
cb(user, null);
};
Console Output
undefined
Login Failed! : Invalid User
connected to user db and preformed lookup.
{ _id: 51c8e16ce295c5b71ac6b229,
user: 'bclark#themindspot.com',
user_type: 'admin_master',
password: 'enter',
first_name: 'Brandon',
middle_name: 'Laurence',
last_name: 'Clark',
birth_date: Fri Mar 19 1982 00:00:00 GMT-0800 (PDT),
join_date: Wed Jun 26 2013 00:00:00 GMT-0700 (PDT) }
db.once and UserModel.findOne are asynchronous functions, hence why you provide an anonymous function that is called when they are done. If you want your isUser function to 'return' the results of these asynchronous functions you will have to make it use a callback as well.
Replace
function isUser(login){
with
function isUser(login, callback){
and
return user;
with
callback(user).
It is also recommended to not throw errors in asynchronous code, but pass them on with the callback, similar to what db.once and UserModel.find do, like so:
Remove
if (err){ throw err; }
and replace the callback above with
callback(err, user);
While you're at it, since you don't do anything with the error or user anymore, you might as well call UserModel.findOne({'user': login}, callback);
===
The complete thing would become the following. Note that I follow the callback(err, result) convention.
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
function isUser(login, callback){
var UsersSchema = new Schema({
user: String,
user_type: String,
password: String,
first_name: String,
middle_name:String,
last_name: String,
birth_date: Date,
join_date: Date
});
var UserModel = mongoose.model('users', UsersSchema);
mongoose.connect('mongodb://localhost/identity');
mongoose.model('users', UsersSchema);
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error: '));
db.once('open', function cb () {
UserModel.findOne({'user': login}, callback);
});
}
module.exports.authenticate = function (login, password, cb) {
var user = isUser(login, function(err, user) {
if (err) {
cb(err);
}
console.log(user);
if (!user) {
msg = 'Invalid User';
cb(msg);
return;
}
if (user.password != password) {
msg = 'Invalid Password';
cb(msg);
return;
}
cb(null, user);
});
};
Finally, consider using (custom) Error objects instead of String messages, google it for explanations as to why.
yes this is a async issue. you may know that node.js every action has a separate thread
in your code you call
var user = isUser(login),
according to You it should return the result from the isUser function but the execution give this function a separate thread and it goes on to the next statement.
as on the next statement the user is undefined because it doesn't return anything from the function isUser
so the statement if (!user) { becomes true
to avoid this error you should place isUser in a callback function
means restrict the execution until and unless you get response from the function