check an item collection value mongodb - node.js

I would like to know what can I do to check an intem of a collection in mongodb.
the function that I describe below insert users in the db and I would check before the insert if the username exists.
exports.adduser = function(db) {
return function(req, res) {
var userName = req.body.username;
var userEmail = req.body.useremail;
var userCod = req.body.usercod;
var collection = db.get('usercollection');
collection.insert({
'username' : userName,
'email' : userEmail,
'cod' : userCod
}, function (err, doc) {
if (err) {
res.send('There was a problem adding the information to the database.');
}
else {
res.location('userlist');
res.redirect('userlist');
}
});
}
}

var collection = db.get('usercollection');
collection.count({username:username}, function(err, count){
if(err){
return callback(err);
}
if(count > 0){
return callback('User already exists!');
}
//do your insert operation
});

I don't know diddly squat about node.js, but lookups in MongoDB are on the Collection object as find() and findOne(). Assuming your username is enough to make a record unique, the "check if exists" would look like
if ( collection.findOne( { "username" : userName } ) != null ) {
println("username " + userName + " exists!" );
}

The obvious approach would be to add a unique index on username, which will ensure you can't insert duplicates.
The error handling logic will be similar to what you've sketched out in the question description. If a username already existed, there would be an exception when trying to insert and the err string would be something like "E11000 duplicate key error... " (including the offending duplicate key).

Related

MongoDB: findOne returns null but document exists in collection

I'm trying to send an email and password server-side and check if a document with those values exists (which it does), but when I console log the results from the query it's null.
Here's the document in the users collection:
{
"_id" : ObjectId("580bcf9874ae28934705c0fc"),
"email" : "johndoe#gmail.com",
"password" : "pass"
}
Here's what I'm sending server-side:
{"email":"johndoe#gmail.com","password":"pass"}
Here's my code (updated):
mongo.connect('mongodb://localhost:27017', function (err, db) {
if (err) {
console.log("error: " + err); // logs nothing
} else {
var users = db.collection("users");
var tasks = db.collection("tasks");
app.post("/login", function(req, res) {
var emailRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var userInDb;
var userEmail = req.body.email;
var userPassword = req.body.password;
console.log(req.body.email); // logs "johndoe#gmail.com"
console.log(req.body.password); // logs "pass"
if (!userEmail || !userPassword) {
return res.sendStatus(403);
} else if ( !emailRegex.test(userEmail)) {
return res.sendStatus(403);
} else {
users.findOne( { "email": userEmail, "password": userPassword }, function(err, results) {
console.log(results); // logs "null"
if(err) {
console.log("error: " + err); // logs nothing
res.sendStatus(403);
} else {
console.log("here"); // logs "here"
res.sendStatus(200);
}
});
}
});
}
});
each time you pass a callback that has an error parameter, it's your responsibility to check if an error was passed, and if so, deal with it.
in your code, you have two such callbacks:
mongo.connect('mongodb://localhost:27017', function (err, db)
users.findOne( { "email": userEmail, "password": userPassword }, function(err, results)
either one of them can return an error object that might explain the issue.
add the following to the first line of each callback:
if (err) {
return console.log("error: " + err);
}
This one worked for me.
I had to call toArray() method.
I don't remember how I found that solution, cuz in MongoDB manuals they don't call to array method
users.findOne( { "email": userEmail, "password": userPassword }).toArray()
I faced a simular problem in one of my project. It is all because I stored the collection and the document in a database which is different from which my app is connected to. Check that once.
It is really mysterious, I think MongoDB client should make a fix on it.
MongoDB is not very reliable. Often get lose connection in 1/10 of requests. But the very annoying is, it returns an empty array instead of an error in connection, that makes us impossible to catch connection error.
Because I use the existence of documents in DB to reinitialize the project, I really get annoyed of it. CouchDB will not have this problem.
users.findOne({'email' : userEmail , 'password':userPassword }, function(err, result) {
console.log("result:"+result);
});

add/edit/delete api, user update data overwrites data in DB nodejs express mongoose

I am writing an API that takes data and stores it into DB, also edits it and deletes it, the add/delete works fine, but when I update I want to be able to update only certain attributes, and if the user doesn't send an attribute I want the code to keep the data already in the DB. Instead if I don't send an attribute it's overwritten by empty data.
Here's an example:
router.post('/update', function (req, res) {
var first_name = req.body.first_name,
last_name = req.body.last_name,
email = req.body.email,
phone_number = req.body.phone_number,
clas = req.body.clas,
subject = req.body.subject,
teacher_id = req.body.teacher_id;
req.assert('teacher_id', 'Invalid teacher_id').notEmpty();
var errors = req.validationErrors();
if (errors) {
res.json(400, {success: false, message: "please enter your teacher_id "});
return;
}
Teacher.findOne({_id: teacher_id}, function (err, teacher) {
if (err) {
console.log(err);
} else {
teacher.first_name = first_name != null || first_name
!= undefined ? first_name : teacher.first_name;
teacher.last_name = last_name != null || last_name
!= undefined ? last_name : teacher.last_name;
teacher.email = email != null || email
!= undefined ? email : teacher.email;
teacher.phone_number = phone_number != null || phone_number
!= undefined ? phone_number : teacher.pickup_points;
teacher.clas = clas != null || clas
!= undefined ? clas : teacher.clas;
teacher.subject = subject != null && subject
!= undefined ? subject : teacher.subject;
teacher.save(function (err, teacher) {
if (err) {
console.log(err);
} else {
res.json({success: true, message: "teacher successfully updated"});
}
});
}
});
});
This may not be the only way, but I use the Lodash library to make this kind of thing easy. I also use the 'param' route to populate the request with my object for me to save callbacks.
const _= require("lodash ")
router.param("teacherId", function(id, req,res,next){
Teacher.findOne({_id : id}, function(e, teacher){
//add error handling of your choice
req.teacher = teacher;
next();
})
})
router.put("teacher/:teacherId", function(req,res){
var updates = _.pick(req.body, ["name","age"]; // whitelist allowed attribute names to change
var teacher = _.merge(req.teacher, updates);
teacher.save(function(e){
// handle your response.
})
})
/* Edit */
Also, please note that in this solution, I'm assuming the use of (reasonably standard) REST-formatted routes. If you want to keep using router.post('/update'... that's fine, but you won't be able to separate out the teacher query like I did.
The advantage of the way I did it is that anytime you want to find a thing first (e.g. viewing a teacher, deleting a teacher, etc), you have the logic for doing so in one place, and don't have to repeat it in other handlers.
This method is a little different from what you are doing but I'd recommend this way to you so that you can keep your document models in one place and call them whenever you need them. Validations part can be handled using a separate module which is for mongoose.
The way you are updating it expects other variables to be assigned as it is, like I am fetching the document using findone then objectname.value = newobjectname.value
A simple way to solve this would be using findoneandupdate.
modelname.findOneAndUpdate({
primarykey: primarykey
}, {
$set: {
nameindocument: valuetobereplace
//you can add here values that you would like to change
}
}, {
new: true //new:true here helps to get updated object in return
}, function(err, doc) {
if (err) {
console.error("Error:" + err);
} else {
}
});

Node.js mongodb update over ObjectID

I want to update my Document but it's not working 100% .
// Initialize connection once
MongoClient.connect("mongodb://localhost:27017/testDB", function(err, database) { //"mongodb://localhost:27017/test"
if(err) throw err;
db = database;
});
My collection row looks like:
{ "_id" : ObjectId("53f9379ce9575bbe9ec29581"), "name:paco",
"status:student" }
Now if I want to update the row over the Document as follows:
db.collection('user', function(err, collection){
collection.update({'_id':ObjectID(req.session.loggedIn)}, {image : filename}, {w:1}, function(err, result){
console.log(result);
I am getting just:
{ "_id" : ObjectId("53f9379ce9575bbe9ec29581"), "image:filename" }
How can I make an update to get my data like this??:
{ "_id" : ObjectId("53f9379ce9575bbe9ec29581"), "name:paco",
"status:student" , "image:filename"}
Doing an update the way you did it is going to retrieve the document in your collection with the specified _id, then it is going to replace the content of this document with what you specified as your second parameter. In your case, it will retrieve the document with _id 53f9379ce9575bbe9ec29581, and replace the existing fields with the field you passed, image:filename (that means the existing fields will be removed, as you noticed).
What you want to do is use the $set operator. This operator will not touch the document retrieved, but only modify the field that you specified, or add it if it does not exist.
So your update command should look something like this:
db.collection('user').update({'_id':ObjectID(req.session.loggedIn)}, {$set: {image : filename}}, {w:1}, function(err, result){
console.log(result);
to update record by _id
var ObjectID = require('mongodb').ObjectID;
exports.updateUser = function(req, res) {
var collection = db.collection('users');
collection.update(where, $set:req.body, function(err, result) {
if (err) {
console.log('Error updating user: ' + err);
res.send({'error':'An error has occurred'});
} else {
console.log('' + result + ' document(s) updated');
res.send(user);
}
});
}

mongodb query with javascript, cursor methods

I am just creating a simple user login for using MongoDB, Backbone and Node with Express.
I am stuck on querying the database for the user credentials and reliably identifying whether they exist or not.
I'm trying two things here:
// When user posts to the url
app.post('/save/user', function (req, res) {
// create user object and store email from form
var user = {
email : req.body.email
};
// in my collection users
db.collection('users', function (err, collection) {
// create a variable existence with the value, in lamens terms 'yes it does' or 'no it doesnt'
var existence = findOne(collection, {
$query : {email : user.email}
});
});
};
// findOne function passing the collection and the query object
function findOne(coll, query) {
var cursor = coll.find(query).limit(1);
return cursor.hasNext() ? cursor.next() : null;
}
So this is the first way I've been trying. Thing is, I don't understand why the cursor doesn't have 'next(), hasNext(), findOne(), forEach()' and other methods for javascript environment but only for mongo shell.
My question is, how do I access these methods from in my Node.js app?
The second way I tried it :
// When user posts to the url
app.post('/save/user', function (req, res) {
// create user object and store email from form
var user = {
email : req.body.email
};
// in my collection users
db.collection('users', function (err, collection) {
// Have a look for the email entered
var query = collection.find({
$query : {email : user.email}
}).limit(1);
// If it's true, then send response
query.each( function (err, item) {
// If the item does exists, then send back message and don't insert. Otherwise, insert.
if(item !== null) {
console.log('Item does not equal null : ', item);
res.send('The email : ' + item.email + ' already exists');
} else {
console.log('Item does equal null : ', item);
collection.insert(user);
res.send('New user with email : ' + user.email + ' was saved');
}
});
});
};
The problem with this is, it's always going to return null at some point and so I am going to warn the user 'it already exists' and then the next time will be null so it's going to save the email.
I think i'm missing the point so a point in the right direction would be great.
Many thanks in advance!
Well i've looked into a solution but still must be missing the point.
I'm doing an insert, passing in my user object with safe : true but although multiple user objects can be entered, it's still only looking for identical ID;s. I've tried creating an id with new ObjectID() but I still don't understand if a user enters their email adress, thenattempts to create a new user with the same email, it would create a new id for that entry.
By doing the findOne, I can see if it exists easily, Idon't see how it can be done with insert.
app.post('/register/user', function (req, res) {
// Store user details in object
var user = {
username : req.body.user,
email : req.body.email,
password : req.body.password
};
db.collection('users', function (err, collection) {
collection.insert(user, {safe : true}, function (err, doc) {
console.log('what is doc : ', doc);
if(!err) {
res.writeHead(200, {
"Content-Type" : "text/plain",
"Message" : "New user added",
"Access-Control-Allow-Origin" : "*"
});
} else {
console.log('Error is : ', err);
res.writeHead(200, {
"Content-Type" : "text/plain",
"Message" : "User already exists",
"Access-Control-Allow-Origin" : "*"
});
}
res.end();
});
});
});
If you're using the Native Node.JS MongoDB driver, there is a collection.findOne() method and cursors do have nextObject() and each() methods equivalent to the shell methods hasNext() and forEach(). The implementation/naming of the mongo shell equivalents can vary slightly between drivers but you should be able to translate mongo shell examples into Node.JS.
As far as saving a new user goes .. instead of querying for the user before inserting, you would be better to add a unique index on the email field and insert into the collection with safe:true. You can then handle the err result if the insert fails due to a duplicate email. If you do a query before insert there is a potential race condition where the email might not exist when you check for it, but does exist by the time you do the insert.

selecting from couchdb in nodejs craddle?

I have couchdb and document my_users whitch looks like:
_id
password
email
...
how can I select _id for _id and password.
I would like sth like mysql select _id from my_users where _id = "mylogin" and password = "mypassword"
i using cradle
and trying sth like this:
db.save('_design/user', {
views: {
byUsername: {
map: 'function (doc) { if (doc.resource === "my_users") { emit(doc._id) } }'
}
}
});
this.db.view('user/byUsername', { key: 'myuser' }, function (err, doc) {
console.dir(doc); ///this is empty array :|
});
but it doesn;t work correctly how to use it ??
You can emit both the _id and password together.
function(doc) {
var key;
if(doc.resource == "my_users") {
key = [doc._id, doc.password];
emit(key, null);
}
}
To find a username/password match, search for the same key.
var username = 'myuser';
var password = 'secret';
var key = [username, password];
this.db.view('users/byUsernamePassword', {"key":key}, function(err, doc) {
console.log("Result:");
console.dir({"err":err, "doc":doc});
})

Resources