Can't find user by name with Monk / Mongo - mongodb

I'm working on a CRUD application with Node, Mongo & Monk.
I'd like to find a record by username, and then update it.
But I'm unable to find a record, this code isn't working:
// GET User Profile
router.get('/userprofile', function(request,response){
var db = request.db;
var userName = request.body.username;
var collection = db.get('usercollection');
collection.findOne({
"username": userName
},{},function(e,user){
response.render('userprofile', {
"user": user
});
});
});
The "findOne" method doesn't return anything, and the "user" object ends up empty.

Remove the middle empty object from the signature for the findOne() method signature for the query to work:
Note: The way you are getting the userName is for when the request method is a POST, here you are doing a GET so you need to use the request.query property. More details here
var userName = request.query.username;
collection.findOne({"username": userName}, function(e,user){
response.render('userprofile', { "user": user });
});
If you want to update then you can use the update() method, suppose you want to update the username field to change it to 'foo', the following stub shows how you can do the update:
var u = collection.update({ "username": userName }, { "$set": { username: 'foo' } });
u.complete(function (err, result) {
console.log(err); // should be null
console.log(result); // logs the write result
});

Ok, I found out the problem.
Chridam's code was correct, but I also needed to change my form from a GET to a POST. Once I did that, the form POSTed and mongo could see request.body.username (it was null before) and look up my user using Chridam's code.
After reading Chridam's revised answer, was also able to get it to work with GET.
Now working on the update code..

Related

ObjectId as key to another collection-Migration

I am trying to add the ObjectId as a "Foreign key" to a collection. I have the previous id to link but I am having problem with the script.
Following is the script
db.users.find().forEach(function (user) {
var cursor = db.po1.find({"owner:": user.ID});
cursor.forEach(function(property) {
property.user_id = user._id;
db.po1.save(property);
});
});
The script runs but I do not get the field added to the documents of the po1 collection.
I am using mongoose for the api so I need the ObjectId. I do not want to embed the documents because of the rarity of the calls and the size of the po1 per user.
user.ID and po1.owner field are of the same type.
Thanks you for your time
From comment the answer.
Although save() has also been deprecated and finally the bellow script did the trick
db.users.find().forEach(function (user) {
var cursor = db.views.find({"user": user.ID});
cursor.forEach(function(object) {
object.userId = user._id;
db.views1.insertOne(object);
});
});
So through the innsert I created new collection and dropped previous.

Use a function in a Mongoose query

I have a basic schema that implements getters/setters:
var User = new Schema( {
username : { type : String , required : true , get: getUsername, set: setUsername }
} );
User.set('toObject', { getters: true , virtuals : true } );
User.set('toJSON', { getters: true , virtuals : true } );
UserModel = mongoose.model('User', User);
setUsername is fairly simple but "randomizes" the username, and obviously getUsername retrieves the original value. Now, everytime I call setUsername, I will get a different "random" string (I mean it's pretty much a hash function).
My question is, can I somehow use the getter in a query?
Like
UserModel.$where( 'this.username.get() == "<somestring>"' ).exec( function( err , users ) {
// do something with the users
}
} ); // here I get MongoError: TypeError: this.username.get is not a function
or
UserModel.find( { $where: function() {
return( getUsername( this.username ) == "<somestring>" )
} } , function( err , users ) {
// do something with the users
} ); // here I get MongoError: ReferenceError: getUsername is not defined
I tried adding a getUsername method to the schema as well, adding virtuals, etc., but I cannot seem to find a solution. i've tried about 15 different syntaxes but I either get an error, an empty array or all users.
Basically if I have a user whose username is "a", it'll be saved in my DB as *"b", "c", "d", or whatever else the setUsername function sets it to.
I'd like to retrieve the user knowing only that their username is "a".
Thank you!
Yes, this should theoretically be possible using query middleware, but you might have to think a little differently:
Let's say you want to run a query like this:
UserModel.find({user: 'a'})
where 'a' is the unscrambled input and you actually want to automatically lookup {user: getUser('a')}, which we'll say is {user: 'b'}
Then you could use this middleware to modify your Query like this:
const userFilter = function (next) {
const query = this.getQuery();
if (query.userName) {
// this transforms the query in-place from {user: 'a'} to {user : 'b'}
query.userName = setUserName(query.userName)};
}
return next();
};
// let's hook this one in!
User.pre('find', userFilter);
Note: This will hook on all queries including ".userName" If you only use UserModel.find() then this will suffice, but otherwise you might also want to register this hook on ['count', 'find', 'findOne', 'findOneAndRemove','findOneAndUpdate', 'remove', 'update', 'updateOne', 'updateMany'] and that some queries (iirc e.g. findByIdAndUpdate) is supposed to bypass mongoose and directly use the mongodbDriver, which might also bypass this hook... Even though it still seems to work currently, so you might want to test all kinds of functions with it)
EDIT:
Looking back at your question, I am not sure, if I understood your question correctly. What does the setUsername function actually return? Is it always the same output for the same input? If so, you basically always to query {userName: setUserName('a')}, right?

Meteor check whether document already exists in collection or not?

I am beginner in meteor. I have a form having username and password as input fields and a submit button in the end.
I have correctly collected data from both fields into two variables. Now what I want is to verify whether any matching document exists in my MongoDB collection or not? My below code is not working. How to do it? Please help. Here is my code.
Template.form.events({
'submit.login':function(event){
event.preventDefault();
var user = document.getElementById("myForm").elements[0].value;;
var pass = document.getElementById("myForm").elements[1].value;
var usernamee = (Collection.Login.find({username: user},{password: pass})).count();
if(usernamee>0) {
alert("found");
} else {
alert("not found");
}
return false;
}
});
Firstly your .find() is incorrect:
var usernamee = (Collection.Login.find({username: user},{password: pass})).count();
shoud be:
var usernamee = (Collection.Login.find({username: user, password: pass})).count();
Assuming that you're publishing that collection to the client either with autopublish or an explicit publication.
However:
You are giving even non-logged in users access to the usernames and cleartext passwords of all other users!
Meteor includes the accounts package that takes care of user management for you. You don't need to reinvent the wheel. You want to take advantage of the security work that's already been done for you.
You can use a method call to find out if a username has already been used and warn the new user in the UI before they create their account.
client:
Meteor.call('usernameExists', username, function(err, result){
if (result) {
alert('Username '+username+' is already taken!')
// clear out the form etc...
}
});
server:
Meteor.methods({
usernameExists(username){
return Meteor.users.findOne({username}) !== 'undefined';
}
});

Query sailsjs blueprint endpoints by id array using request

I'm using the request library to make calls from one sails app to another one which exposes the default blueprint endpoints. It works fine when I query by non-id fields, but I need to run some queries by passing id arrays. The problem is that the moment you provide an id, only the first id is considered, effectively not allowing this kind of query.
Is there a way to get around this? I could switch over to another attribute if all else fails but I need to know if there is a proper way around this.
Here's how I'm querying:
var idArr = [];//array of ids
var queryParams = { id: idArr };
var options: {
//headers, method and url here
json: queryParams
};
request(options, function(err, response, body){
if (err) return next(err);
return next(null, body);
});
Thanks in advance.
Sails blueprint APIs allow you to use the same waterline query langauge that you would otherwise use in code.
You can directly pass the array of id's in the get call to receive the objects as follows
GET /city?where={"id":[1, 2]}
Refer here for more.
Have fun!
Alright, I switched to a hacky solution to get moving.
For all models that needed querying by id arrays, I added a secondary attribute to the model. Let's call it code. Then, in afterCreate(), I updated code and set it equal to the id. This incurs an additional database call, but it's fine since it's called just once - when the object is created.
Here's the code.
module.exports = {
attributes: {
code: {
type: 'string'//the secondary attribute
},
// other attributes
},
afterCreate: function (newObj, next) {
Model.update({ id: newObj.id }, { code: newObj.id }, next);
}
}
Note that newObj isn't a Model object as even I was led to believe. So we cannot simply update its code and call newObj.save().
After this, in the queries having id arrays, substituting id with code makes them work as expected!

how to check whether username and password exists inside database(mongodb)

i want to store username and password inside mongodb database and later on retrieve database values and check whether the username and password exists inside database.If it does exist then i would redirect to another page.How can i achieve this using node.js and mongodb.I am able to store the values inside database.But getting confused for how to fetch the values and check them against the values provide in form field values.There is no method in mongodb like fetchByName or something similar.
Can someone help me out with the code.
I think you should take a look on the Nodepad source code, it explains very well how to achieve this with Mongoose:
User.virtual('password')
.set(function(password) {
this._password = password;
this.salt = this.makeSalt();
this.hashed_password = this.encryptPassword(password);
})
.get(function() { return this._password; });
User.method('authenticate', function(plainText) {
return this.encryptPassword(plainText) === this.hashed_password;
});
User.method('makeSalt', function() {
return Math.round((new Date().valueOf() * Math.random())) + '';
});
User.method('encryptPassword', function(password) {
return crypto.createHmac('sha1', this.salt).update(password).digest('hex');
});
User.pre('save', function(next) {
if (!validatePresenceOf(this.password)) {
next(new Error('Invalid password'));
} else {
next();
}
});
try using an already existing library like passport or everyauth. There are other ones too, google them :)