What is the best method to check if field value already exists.
This is my model:
// Set global
var moment = require('moment');
var _ = require('lodash');
// Create model
module.exports = function (orm, db) {
var Profile = db.define('profile',
// Field Properties
{
username: {type: 'text', required: true, unique: true},
name: {type: 'text', required: true},
email: {type: 'text', required: true},
password: {type: 'text', required: true},
birthday: {type: 'date', required: true},
gender: {type: 'enum', values: ["male", "female"], required: true},
join_date: {type: 'date'}
},
{
// Model hooks. Manual: https://github.com/dresende/node-orm2/wiki/Model-Hooks
hooks: {
beforeValidation: function() {
// Set join date to current date
this.join_date = new Date();
}
},
// Model Validations. Manual: https://github.com/dresende/node-orm2/wiki/Model-Validations
validations: {
username: [orm.enforce.security.username({length: 4}, 'Invalid username')],
email: [orm.enforce.patterns.email('Please enter a valid email')],
password: [orm.enforce.security.password('6', 'Invalid password')],
birthday: [orm.enforce.patterns.match(/\d{2}-\d{2}-\d{4}/, null, 'Invalid birthday')]
},
// Model methods. Extra functions and stuff
methods: {
}
});
};
And this is my register controller:
module.exports = function (req, res, next) {
// Get post params
var params = _.pick(req.body, 'formAction', 'username', 'password', 'email', 'confirm_password',
'birthday', 'gender', 'terms');
// If we try to register
if (params['formAction'] == 'register') {
// Manual validations
// Check if we agreed with the terms
if (params['terms'] != 1) {
res.send({error: 'You must agree to the terms of service'});
return false;
}
// Check if password was confirmed
if (params['password'] && params['password'] != params['confirm_password']) {
res.send({error: 'Please confirm your password'});
return false;
}
// Check if username already exists
// Try to register
req.models.profile.create({username: params['username'],
password: params['password'],
email: params['email'],
birthday: params['birthday'],
gender: params['gender'],
name: params['username']}, function (err, items) {
// Check to see if we have error
error = helpers.getError(err);
// Return error
if (error)
res.send({error: error});
});
}
// Show login form
else
res.sendfile(settings.path + '/public/register.html');
};
How can i check if username already exists in db? Now if i try to create i get DUP_KEY error from database.
Thanks,
Radu
Looks like adding a hook and using next() worked out
beforeCreate: function (next) {
obj = this;
Profile.exists({email: this.email}, function (err, exists) {
if (exists) {
return next(new Error("Email already exists"));
}
else
{
Profile.exists({username: obj.username}, function (err, exists) {
console.log(exists);
if (exists) {
return next(new Error("Username already exists"));
}
else
return next();
});
}
});
}
Related
Node js with mongoose.
model has fields that are not selected by default queries(select:false in model). In some scenarios I need to test the result to have the field selected. I have tried sinon-mongoose but it just tells me if a populate or select method was called, but for more flexibility I need to check the result data. And a requirement is not to use any real db connection, as it is a unit test.
The model
var DoctorSchema = new Schema({
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true
},
middleName: {
type: String
},
institutionName: {
type: String,
required: true,
select: false
}
});
The Service
module.exports = function (Doctor) {
service.getById = function(req, res, next){
Doctor.findOne({"_id" : req.params.id}).select('+institutionName').exec(function (err, doc) {
if (err) {
console.log(err);
return
};
if (!doc) {
res.send(404);
}
else {
res.json(doc);
}
});
}
}
So this can be tested
describe('doctorService getById', function () {
it('presentationService should call getById', function (done) {
var DoctorMock = sinon.mock(DoctorModel);
DoctorMock
.expects('findOne').withArgs({ "_id": "123" })
.chain("select").withArgs('+institutionName')
.chain('exec')
.yields(null, seed.doctor);
var serviceMock = doctorService(DoctorModel);
var res = {
json: function (data) {
DoctorMock.verify();
DoctorMock.restore();
assert.equal(seed.doctor, data, "Test fails due to unexpected result");
done();
}
};
serviceMock.getById({param:{id:"123"}}, res);
});
});
But in my example the test is bound to the chain. My intuition tells me that this is not a good approach.
I need to build a chat using nodejs and mongodb. In this chat I need to mount the contact list by ordering the latest posts and applying paging 15 items per page. I wonder how I can do this dynamically using mongodb / mongoose.
For example, on the first page I seek contacts ordered by those who sent messages last. If loading the second page, and any new message has arrived, the order of chatlist have probably changed.
How I can ride my query and do this treatment?
My User Schema is:
var schema = new Schema({
name: {type: String, required: true},
email: {type: String, required: true, unique: true},
password: {type: String, required: true, select: false},
created_at: {type: Date, required: true, default: Date.now}
});
My Message Schema is:
var schema = new Schema({
content: {type: String, required: true},
type: {type: String, required: true, default: 'text'},
status: {type: String, default: 'not_read'},
created_at: {type: Date, default: Date.now},
read_at: {type: Date},
userFrom: {type: Schema.Types.ObjectId, ref: 'User', required: true},
userTo: {type: Schema.Types.ObjectId, ref: 'User', required: true}
});
Thank you in advance.
EDIT 1:
var itensPerPage = 15;
var skip = page !== undefined ? page * itensPerPage : 0;
pages = Math.ceil(pages / itensPerPage);
Message
.aggregate([
{ '$sort': {
'created_at': -1
}},
{ "$skip": skip },
{ "$limit": itensPerPage },
{ '$match': {
$or: [
{ userFrom: psychologist.id_user },
{ userTo: psychologist.id_user }
]
}},
{ '$group': {
'_id': {
'userFrom': '$userFrom',
'userTo': '$userTo'
},
}
},
])
.exec(function (err, id_users) {
if(err){
callback(new Error("Something went wrong while trying to agregate the psychologist users."), null);
}else{
var users_from_id_map = id_users.map(function(x) { return x._id.userFrom} );
var users_to_id_map = id_users.map(function(x) { return x._id.userTo} );
var chatlist = [];
var received = users_from_id_map.length;
for(var i = 0; i < users_from_id_map.length; i++){
Message
.findOne({$or : [{userFrom: users_from_id_map[i], userTo: users_to_id_map[i]}]})
.sort('-created_at')
.exec(function (err, message) {
if(err){
callback(new Error("Something went wrong while trying to find last message."), null);
}else{
if(message){
var user_chat_id;
if(psychologist.id_user.equals(message.userFrom)){
user_chat_id = message.userTo;
}else{
user_chat_id = message.userFrom;
}
var is_mine = false;
if(message.userFrom.equals(psychologist.id_user)){
is_mine = true;
}
chatlist.push({
id_user: user_chat_id,
lastMessage: {
content: (message.content.length > 35 ? message.content.substring(0,35)+"..." : message.content),
date: message.created_at,
is_mine: is_mine
}
});
}else{
chatlist.push({
id_user: user_chat_id,
lastMessage: null
});
}
received--;
if(received == 0){
next(err, psychologist, chatlist, pages);
}
}
});
}
}
});
Paging can be implemented in various ways in MongoDB.
You could use limit and offset although this will become slow when requesting higher pages.
Another way is to use greaterThan with the last contact you have seen together with limit to, say, get the next 15 contacts.
Inconsistencies (if new messages are send during paging) cannot easily be prevented.
That said, MongoDB may not be a good choice for a live chat because it has no support for streaming queries.
This question already has answers here:
Mongoose Unique index not working!
(35 answers)
Closed 6 years ago.
I am trying to sign up a new user via Angular app, but when I am registering a user with the same username, Mongo allows me to do this, so it does not reurn an error and afterwards I can see two users with same names in the db. But I do mark name field as unique.
part of api:
apiRoutes.post('/signup', function(req, res) {
if (!req.body.userId || !req.body.password) {
res.json({success: false, msg: 'Please pass name and password.'});
} else {
var newUser = new User({
name: req.body.name,
password: req.body.password,
wallet: req.body.wallet,
userPic: req.body.userPic
});
// save the user
newUser.save(function(err) {
if (err) {
return res.json({success: false, msg: 'Username already exists.'});
}
res.json({success: true, msg: 'Successful created new user.'});
});
}
});
model code:
// set up a mongoose model
var UserSchema = new Schema({
name: {
type: String,
unique: true,
required: true
},
password: {
type: String,
required: true
},
wallet: {
type: Number,
required: true
},
userPic: {
type: String,
required: true,
unique: true
}
});
And POST request code(login and password are taken from outside):
let newUser = {
password: password,
wallet: 0,
userPic: md5(login),
name: login
};
this.$http.post('http://127.0.0.1:8080/api' + '/signup', newUser);
try in your model:
name: {
type: String,
index:{unique: true},
required: true
}
Im trying to implement passsport on an old project and the scema's are set up to be nested for different things for example the name schema below is my sub schema.(There are more this is just for an example)
var nameSchema = new Schema(
{
_id: false,
"firstname" : {type: String, required: true},
"lastname" : {type: String, required: true}
});
// Schema setup
var schema = new Schema(
{
local :
{
name : nameSchema,
email : { type: String, required: true, trim: true, unique: true, select: true},
password : { type: String, required: true, trim: true, select: true},
regDate : { type: Date, select: false, createdAt: true},
alevel : { type: Number, min : 1, max : 5, default: 1, select: true },
}
});
But when I go to add this to my local strategy I get an error TypeError: Cannot set property 'firstname' of undefined How are nested json strategies implemented.
Currently what I have is:
passport.use('local-signup', new LocalStrategy({
usernameField : 'email',
passwordField : 'password',
aLevelField : 'aLevel',
namefield : {
firstnameField : 'firstname',
lastnameField : 'lastname'
},
passReqToCallback : true
},
function(req, email, password, done) {
process.nextTick(function() {
User.findOne({ 'local.email' : email }, function(err, user) {
if (err){
return done(err);
}
if (user){
return done(null, false, req.flash('signupMessage', 'That email is already taken.'));
} else {
var user = new User();
user.local.email = email;
user.local.password = password;
user.local.aLevel = req.body.aLevel;
user.local.name.firstname = req.body.firstname; // <-- error
user.local.name.lastname = req.body.lastname;
console.log('after define',user);
user.save(function(err){
if (err){
console.log(err)
throw err;
}
return done(null, user);
});
}
});
});
}));
Just incase anyone also comes across this and cant figure it out. When I called
user.local.name.firstname = req.body.firstname this from what i can assume was trying to access .name.firstname but because it was empty there was nothing to set .firstname too.
To fix it do:
user.local.name = {
firstname : req.body.firstname,
lastname : req.body.lastname
};
I have found several of these question on here, however the ones I have found deal mostly with HTML, I am having this problem on submitting of a login in java.
Very Simple Save Function
var model = require('../../models/User')
exports.save= function(req,res){
model.findById(req.body.id,function(err,doc){
if(!doc) doc = new model()
doc.email = req.body.email
doc.password = req.body.password
doc.save(function(err){
if(err){
req.flash('error',err)
}
else{
req.flash('success','User saved')
res.redirect('/')
}
})
})
}
my model is very long but here is a sample of it
//define schema
schema = new mongoose.Schema({
email: {
label: 'Email',
type: String,
lowercase: true,
unique: true,
required: true,
index: true,
validate: [
validate('len','6','100'),
validate('isEmail')
]
},
password: {
label: 'Password',
type: String,
required: true,
select: false,
get: function(){ return '********' },
set: function(v){
return bcrypt.hashSync(v,bcrypt.genSaltSync(12))
},
validate: [
validate('len','8','64')
]
},
model = mongoose.model('User',schema)
exports.name = 'user'
exports.description = 'User Model'
exports.schema = schema
exports.model = model
Submits to the function via modal and on every submit I get the err
TypeError: Object #<Object> has no method 'findById' at exports.save
Any help or ideas would be greatly appreciated
Change
var model = require('../../models/User')
to
var model = require('../../models/User').model
Also see the documentation on modules.