mongoose document.save not working - node.js

I am trying to create a very simple forum using nodejs, mongo and mongoose.
So far I created a mongoose Schema for users:
var mongoose = require('mongoose');
var user = {
_id: { type: String, required: true },
password: { type: String, required: true }
};
var schema = new mongoose.Schema(user);
module.exports = schema;
module.exports.user = user;
Then created the Model:
var mongoose = require('mongoose');
var url = 'mongodb://localhost:27017/forum'
mongoose.connect(url);
mongoose.connection.on('connected', function() {
console.log('Stablished connection on ' + url);
});
mongoose.connection.on('error', function(error) {
console.log('Something wrong happened: ' + error);
});
mongoose.connection.on('disconnected', function() {
console.log('connection closed');
});
var User = mongoose.model('User', require('./user'));
module.exports.User = User;
Finally, there is the file that contains all the models (currently just one) and its methods:
var models = require('./models');
var User = models.User
exports.addUser = function(user, password) {
var data = new User({ _id: user, password: password });
data.save(function(error) {
console.log('inside');
if(error) { console.log('ERROR: ' + error); return true; }
else { console.log('User ' + user + ' added'); return false; }
});
};
exports.getUserList = function() {
User.find().lean().exec(function(error, users) {
if(error) { console.log('ERROR: ' + error); }
else { return JSON.stringify(users); }
});
}
The problem comes when I execute this file:
var mongodb = require('mongodb');
var mongoose = require('mongoose');
var dm = require('./dm');
var users = { 'user1': '1234',
'user2': '1234',
'user3': '1234',
'user4': '1234'
};
console.log('Initial user list');
dm.getUserList();
for(var user in users) {
dm.addUser(user, users[user]);
}
console.log('Final user list');
dm.getUserList();
process.exit(0);
It seems that it does nothing and does not save the users. Output:
Initial user list
Final user list
Thanks!

Remove the process.exit() part, or wrap it in a timeout. You don't give your database enough time to execute. E.g. put this at the end instead:
...
setTimeout(() => process.exit(0), 2000);
Edit: or add promises, like somebody commented:
exports.addUser = function(user, password) {
var data = new User({ _id: user, password: password });
return data.save()
.then(() => console.log('User ' + user + ' added'))
.catch(function(error) {
console.log('ERROR: ' + error);
else { return false; }
});
};
Then in your main loop:
const promises = users.map(userData => addUser(userData));
Promise.all(promises)
.then(() => {
console.log('All users added.');
// .. do another async operation here, or process.exit();
});

Related

MongoDB update if user not exists

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 received an error when I delete an index from elasticsearch

I received an error when I manually deleted an index from elasticsearch. This happen after manually deleted and I use User.search function in the route. This is the error:
Error: [search_phase_execution_exception] all shards failed
The reason why I manually deleted the index is because mongoosastic has a known issue where, whenever I delete documents from mongodb, elasticsearch still has the documents with it.
Here's the code
models/user.js
var mongoose = require('mongoose');
var mongoosastic = require('mongoosastic');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
private: false,
twitter: String,
tokens: Array,
username: String,
displayName: String,
picture: String,
});
UserSchema.plugin(mongoosastic, {
hosts: [
'localhost:9200'
]});
module.exports = mongoose.model('User', UserSchema);
router.js
User.createMapping(function(err, mapping) {
if (err) {
console.log('error creating mapping (you can safely ignore this)');
console.log(err);
} else {
console.log('mapping created!');
console.log(mapping);
}
});
var stream = User.synchronize();
var count = 0;
stream.on('data', function(err, doc){
count++;
});
stream.on('close', function(){
console.log('indexed ' + count + ' documents!');
});
stream.on('error', function(err){
console.log(err);
});
/* The result for searching for User's */
router.get('/search', function(req, res, next) {
console.log(req.query.q);
if (req.query.q) {
User.search({
query_string:
{ query: req.query.q }
}, function(err, results) {
if (err) return next(err);
console.log(results);
var data = results.hits.hits.map(function(hit) {
return hit;
});
console.log(data);
return res.render('main/search_results', { data: data });
});
}
});

Cannot read property 'collection' of undefined while connecting to mongodb in node.js?

I am trying to login from my signin.ejs file,after click on the login button in
my signin page it shows "Cannot read property collection undefined" what is the
problem.
I defined my route like this in app.js:
app.post('/login', routes.dologin);
I defined my dologin route in index.js:
exports.dologin = function (req, res) {
res.locals.session = req.session;
var user = req.body.user;
db.authenticateUser(user.email, user.password, function ( err, response) {
if (err) {
.......
.......
} else {
.......
........
}
});
};
In my db.js:
var mongo = require('mongoskin'),
crypto = require('crypto');
module.exports = function (config) {
var USERS_COLLECTION = 'users',
ORDERS_COLLECTION = 'orders',
salt = 'supersecretkey',
db;
authenticateUser: function (emailId, password, callback) {
db.collection(USERS_COLLECTION).count({email : emailId, password: encryptPassword(password)}, function (err, count) {
if (err) {
console.log("error authenticating user: " + err);
callback(new Error(err));
} else if (count === 0) {
callback(new Error("emailid/password did not match"));
} else {
callback(null);
}
});
},
}
What is the problem here for getting "Collection undefined"? i think here
everything is right... Is there any problem here?tell me..please Thanks.
You should add this code db = mongo.db('localhost:27017/yourdb');
var mongo = require('mongoskin'),
crypto = require('crypto');
module.exports = function (config) {
var USERS_COLLECTION = 'users',
ORDERS_COLLECTION = 'orders',
salt = 'supersecretkey',
db = mongo.db('localhost:27017/yourdb');
authenticateUser: function (emailId, password, callback) {
db.collection(USERS_COLLECTION).count({
email: emailId,
password: encryptPassword(password)
}, function (err, count) {
if (err) {
console.log("error authenticating user: " + err);
callback(new Error(err));
} else if (count === 0) {
callback(new Error("emailid/password did not match"));
} else {
callback(null);
}
});
},
}

CRUD on nested schemas using Mongoose

I am trying to set up my nodejs app with a CRUD for mongodb sub-docs using Mongoose but can't figure out how to access the nested object's _id. I can only get the parent ObjectId. I can perform a .push on a new child object but can't perform a simple get, put or delete on an existing child object.
Here is my schema:
//new user model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
// Task schema
var taskSchema = mongoose.Schema({
clientEasyTask : { type: String },
clientHardTask : { type: String },
clientStupidTask : { type: String }
});
var userSchema = new mongoose.Schema({
email: { type: String, unique: true, lowercase: true },
password: String,
task : [taskSchema]
});
module.exports = mongoose.model('Task', taskSchema);
module.exports = mongoose.model('User', userSchema);
Here is my routes:
'use strict';
var isAuthenticated = require('./middleware/auth').isAuthenticated,
isUnauthenticated = require('./middleware/auth').isUnauthenticated;
var User = require('./models/user');
var Task = require('./models/user');
// Create user.task
module.exports = function (app, passport) {
app.post('/api/tasks', isAuthenticated, function (req, res) {
var userEmail = req.body.email;
var easyTask = req.body.easyTask;
User.findOne({ 'email' : userEmail }, function(err, user) {
console.log('found user and defining status and data');
var status;
var data;
if (err) {
status = 'error';
data = 'unknown error occurred';
}
if (user === null) {
status = 'error';
data = 'user not found';
} else {
status = 'ok';
data = user;
}
user.task.push({
clientEasyTask: easyTask
});
user.save();
res.json({
response: {
'status': status
}
});
});
});
// Get one user.task
app.get('/api/tasks/:id', function (req, res) {
return Task.findById(req.params.id, function(err, task) {
if(!task) {
res.statusCode = 404;
return res.send({ error: 'Not found' });
}
if(!err) {
return res.send({ status: 'OK', task:task });
} else {
res.statusCode = 500;
console.log('Internal error(%d): %s', res.statusCode, err.message);
return res.send({ error: 'Server error' });
}
});
});
};
I am using Postman to test everything so there is no fronted code. When I pass the _id of the task (nested in the user) I receive null when I call Get on '/api/tasks/:id'. How can I can get only the specific task?
The mongoose documentation states that you can use parent.children.id(id); but I couldn't get it to work.
The task field of User contains the tasks as embedded subdocs, not references to another collection, so you can't query tasks independent of users (like you're trying to do).
To query for the embedded task subdoc, you can use a query like this:
User.findOne({'task._id': req.params.id})
.select('task.$') // Just include the matching task element
.exec(function(err, user) {
if(!user) {
res.statusCode = 404;
return res.send({ error: 'Not found' });
}
if(!err) {
// The matching task will always be in the first element of the task array
return res.send({ status: 'OK', task: user.task[0] });
} else {
res.statusCode = 500;
console.log('Internal error(%d): %s', res.statusCode, err.message);
return res.send({ error: 'Server error' });
}
}
);
To make this efficient, you'd want to add an index on {'task._id': 1}.

Node Async not executing the db function

I am sending a post request from a form but async.waterfall() doesn't execute the mongoose's User.find() function to fetch users from the database and as a result the post request's status in the network inspector is pending as res.send() is not being called.
exports.createUser = function(req,res){
var email1 = req.body.mail.toString();
var password = req.body.password.toString();
async.waterfall([
function(callback) {
// verify user in the db
User.find({email:email1},function(err,data){
if (err){
res.send(404);
return callback(err);
}
// user is found
if (data.length != 0){
res.send(404);
return callback(new Error("User Found"));
}
callback();
});
},
// generate salt password
function(callback) {
bcrypt.genSalt(SALT_WORK_FACTOR,function(err,salt){
if (err) return callback(err);
bcrypt.hash(password,salt,function(err,hash){
if (err) return callback(err);
return callback(null,hash);
});
});
},
//generate random string
function(hash,callback){
crypto.randomBytes(48,function(err,buf){
if (err) return callback(err);
var randomString = buf.toString('hex');
return callback(null,hash,randomString);
});
},
// save them in the mongoDb using mongoose
function(hash,randomString,callback){
var userModel = new User;
userModel.email = email1;
userModel.password = hash;
userModel.verificationId = randomString;
userModel.save();
callback(null,'done');
}
],function(err){
if (err){
console.log(err);
res.send(404);
} else{
console.log("done");
res.send("200");
}
});
}
Here is my app.js file using express
// render the registration page
app.get('/users/create',register.renderUserPage);
app.post('/users/create',function(req,res){
register.createUser(req,res);
});
Here is the Db.js file which connects to mongoDb using mongoose
console.log("connection succeeded");
var UserSchema = new Schema ({
email: {type:String ,require : true ,index : {unique : true}} ,
password:{ type : String ,required: true} ,
verificationId:{type:String, required:true,index:true}
});
UserSchema.plugin(ttl,{ttl:90000000});
module.exports = mongoose.model('User',UserSchema);

Resources