Mongoose error in required properties - node.js

I'm connecting a Angular 2 app to MongoDB via Mongoose.
I'm trying to store some data, but i obtain an error on all required properties.
I set up a schema, serverside:
var mongoose = require("mongoose");
var Schema = mongoose.Schema;
var uniqueValidator = require("mongoose-unique-validator");
var schema = new Schema({
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
},
nome: {
type: String,
required: true
},
cognome: {
type: String,
required: true
},
dataNascita: {
type: Date
},
telefono: {
type: String
},
classifica: {
type: String
}
});
schema.plugin(uniqueValidator);
module.exports = mongoose.model("User", schema);
The user object is clearly filled:
Mongoose responds with an error:
Thanks in advance for any help.
Max
Update:
The call from a Angular service:
#Injectable()
export class AuthService {
constructor(private http: Http) {
}
addUser(utente: Utente) {
const body = JSON.stringify(utente);
return this.http.post('http://localhost:3000/utente', body)
.map((response: any) => {
console.log(response);
response.json();
})
.catch((error: Response) => Observable.throw(error.json()
));
}
}
The Moongose call:
var express = require('express');
var router = express.Router();
var User = require('../models/users');
router.post('/', function (req, res, next) {
var user = new User({
email: req.body.email,
password: req.body.password,
nome: req.body.nome,
cognome: req.body.cognome,
dataNascita: req.body.dataNascita,
telefono: req.body.telefono,
classifica: req.body.classifica
});
console.log(res);
user.save(function (err, result){
console.log(err);
console.log(res);
if (err){
return res.status(500).json({
titolo: "Errore durante il salvataggio",
errore: err
});
}
res.status(201).json({
messaggio: 'Utente salvato correttamente',
oggetto: res
});
});
});

Related

cant update in mongoDb with mongoose

I am trying to create a followers/following function in my project. However I cannot seem to update the DB correctly. I'm able to send the ids as they both print when I console.log but nothing in my DB updates and I do not get any response in my frontend.
route
app.put('/api/follow', async function (req, res, next){
const { id } = req.query;
const userFrom = req.body.data
console.log('OTHER USER ID',id)
console.log('CURRENT ID', userFrom)
User.findByIdAndUpdate(id), {
$push:{followers:req.body.data}
},{new:true},
(err,result)=>{
if(err) {
if(err) return res.status(400).send(err)
}
User.findByIdAndUpdate(req.body.data), {
$push:{following:id}
},{new:true}.then(result=> {
res.json(result)
}).catch(err=>{
return res.status(422).json({error:err})
})
}
})
user model
const mongoose = require("mongoose");
const User = mongoose.model(
"User",
new mongoose.Schema({
username: String,
email: String,
password: String,
phoneNo: String,
bio: String,
filePath: String,
following: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
],
followers: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
})
);
module.exports = User;
my route end function
const clickHandler = () => {
const currentID = currentUser.id;
const id = this.props.id;
console.log('CURRENT ID',currentID)
console.log('otherUserID',id)
Axios.put(`http://localhost:8080/api/follow/?id=${id}`, { data: currentID }, { headers: authHeader() })
.then(response => {
if (response.data.success) {
console.log('FOLLOWED', response.data)
// this.setState({ userDetails: response.data.details })
} else {
alert('Error')
}
})
}
This should be
User.findByIdAndUpdate(id, {
You should not close the bracket after id but after new: true})

Mongoose userModel is not defined

I'm pretty new with nodejs and mongoDB. I have created a registration and user schema but it doesn't recognize this and send the following error:
ReferenceError: userModel is not defined
When I trace the error, I found that it doesn't recognize this keyword.
Here is user.js code:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var bcrypt = require('bcrypt');
var userSchema = new Schema({
teamName: {
type: String,
unique: true,
trim: true,
required: true
},
faculty: {
type: String,
required: true
},
email: {
required: true,
unique: true,
trim: true,
type: String
},
password: {
required: true,
type: String
},
score: {
type: Number,
default: 0
}
});
userSchema.pre('save', function(next) {
var user = this;
bcrypt.hash(user.password, 10, (err, hash) => {
if (err) return next(err)
user.password = hash;
next();
});
})
var userModel = mongoose.model('User', userSchema);
module.exports = userModel;
server.js
router.post('/register', (req, res) => {
var newUser = {
teamName: req.body.teamName,
faculty: req.body.faculty,
email: req.body.email,
password: req.body.password
}
userModel.create(newUser, (err, user) => {
if (err) {
console.log('[Registratoin]: ' + err);
} else {
console.log(user)
console.log('[Registration]: Done');
// req.session.userID = user._id;
res.redirect('/scoreboard')
}
});
});
The this keyword in the pre-save hook in your model is not the issue.
ReferenceError: userModel is not defined
ReferenceError: "x" is not defined means that the userModel is undefined from the scope you're calling it from. (Thus you're referencing a non-existent value)
I have include it like var userModel = require('the_path')
As you're requiring and exporting the userModel correctly. I would double check the path you're importing the module from.

Mongoose: cannot insert/find records

I am new in mongoose and I'm facing some problem in it.
After running the following code, neither success nor error message is shown. And when I browse the webpage, there is no response.
Is there any problem in my code?
const http = require("http");
const mongoose = require("mongoose");
mongoose.Promise = global.Promise;
mongoose.connect("mongodb://localhost/node_tut", { useMongoClient: true});
const StudentSchema = new mongoose.Schema({
first_name: { type: String, required: true },
last_name: { type: String, required: true },
class: { type: String, required: true },
class_num: { type: Number, min: 1, required: true }
});
let Student = mongoose.model('student', StudentSchema);
let peter = new Student({
first_name: "Peter",
last_name: "Chan",
class: "1A",
class_num: 2
});
peter.save((err) => {
if(err){
console.log("Error inserting Peter");
return;
}
console.log("inserting Peter");
});
let mary = new Student({
first_name: "Mary",
last_name: "Hung",
class: "1A",
class_num: 6
});
mary.save((err) => {
if(err){
console.log("Error inserting Mary");
return;
}
console.log("inserting Mary");
});
const server = http.createServer((req, res) => {
// Send the HTTP header
// HTTP Status: 200 : OK
// Content Type: text/plain
res.writeHead(200, {'Content-Type': 'text/plain'});
console.log("request");
Student.find({}, (err, students) => {
console.log("result founded");
if(err){
res.end(err);
return;
}
res.end(students.toString());
});
});
server.listen(3000);

Mongoose: How to prevent mongodb to save duplicate email records in database

I want to make the key email unique across that collection but i cant getting this working, here is my server code.
// Create a schema
var userSchema = new mongoose.Schema({
email: { type: String, required: true},
password: String
});
var userModel = mongoose.model("user", userSchema);
router.post('/postuser', (req, res) => {
console.log('Requested data to server: ' + JSON.stringify(req.body._user));
var user = new userModel({
email: req.body._user.email,
password: req.body._user.password
});
// user.isNew = false;
user.save((err, data) => {
console.log('Analyzing Data...');
if(data) {
console.log('Your data has been successfully saved.');
res.json(data);
}
else {
console.log('Something went wrong while saving data.');
console.log(err);
res.send(err);
}
})
});
Note: I also try email: { type: String, required: true, unique: true} but its not working and show below error.
name: 'MongoError',
message: 'E11000 duplicate key error collection: hutreservationsystem.users
index: _Email_1 dup key: { : null }',
driver: true,
code: 11000,
index: 0,
errmsg: 'E11000 duplicate key error collection: hutreservationsystem.users index: _Email_1 dup key: { : null }',
getOperation: [Function],
toJSON: [Function],
toString: [Function] }
A short answer using this tool mongoose-unique-validator
npm install --save mongoose-unique-validator
and in your model
var mongoose = require('mongoose')
var uniqueValidator = require('mongoose-unique-validator')
var userSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true},
password: String
});
userSchema.plugin(uniqueValidator)
var userModel = mongoose.model("user", userSchema);
That's it! (Notice unique: true)
Now, there is no email duplication in your collection.
Bonus! : you can access err
.catch(err => console.log(err))
so in your example
// user.isNew = false;
user.save((err, data) => {
console.log('Analyzing Data...');
if(data) {
console.log('Your data has been successfully saved.');
res.json(data);
}
else {
console.log('Something went wrong while saving data.');
console.log(err);
res.send(err);
}
accessing err >>
so you can res.send(err.message) >> 'Validation failed'
{
message: 'Validation failed',
name: 'ValidationError',
errors: {
email: {
message: 'Error, expected `email` to be unique. Value: `example#gmail.com`',
name: 'ValidatorError',
kind: 'unique',
path: 'email',
value: 'example#gmail.com'
}
}
}
Async Custom Validator
var userSchema = new mongoose.Schema({
password: String,
email: {
type: String,
lowercase: true,
required: true,
validate: {
isAsync: true,
validator: function(value, isValid) {
const self = this;
return self.constructor.findOne({ email: value })
.exec(function(err, user){
if(err){
throw err;
}
else if(user) {
if(self.id === user.id) { // if finding and saving then it's valid even for existing email
return isValid(true);
}
return isValid(false);
}
else{
return isValid(true);
}
})
},
message: 'The email address is already taken!'
},
}
});
You may like to change the validator code to es6.
email: {
type: String,
trim: true,
unique: true, // note - this is a unqiue index - not a validation
validate: {
validator: function(value) {
const self = this;
const errorMsg = 'Email already in use!';
return new Promise((resolve, reject) => {
self.constructor.findOne({ email: value })
.then(model => model._id ? reject(new Error(errorMsg)) : resolve(true)) // if _id found then email already in use
.catch(err => resolve(true)) // make sure to check for db errors here
});
},
}
},
I implemented the following code to see if anything was wrong:
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var express = require('express');
var http = require('http');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
var Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/test');
// Create a schema
var userSchema = new mongoose.Schema({
email: { type: String, required: true, unique: true},
password: String
});
var userModel = mongoose.model("user", userSchema);
app.post('/postuser', (req, res) => {
console.log('Requested data to server: ' + JSON.stringify(req.body._user));
var user = new userModel({
email: req.body._user.email,
password: req.body._user.password
});
// user.isNew = false;
user.save((err, data) => {
console.log('Analyzing Data...');
if(data) {
console.log('Your data has been successfully saved.');
res.json(data);
}
else {
console.log('Something went wrong while saving data.');
console.log(err);
res.send(err);
}
})
});
http.createServer(app).listen(3000, function(){
console.log('Express server listening on port 3000');
});
And I made sure that no collection by the name of users existed in my local MongoDB database. Moreover, I used Postman for sending API requests to my server at http://localhost:3000. There seemed to be no issue as I continued to add users with differing email values. And I only got the following error when I entered an email with a duplicate value
{
"code": 11000,
"index": 0,
"errmsg": "E11000 duplicate key error collection: test.users index: email_1 dup key: { : \"hot#mail.com\" }",
"op": {
"email": "hot#mail.com",
"password": "1234567",
"_id": "5919a3428c13271f6f6eab0f",
"__v": 0
}
}
These are the JSON requests that I sent:
{"_user": {"email": "hot#mail.com", "password": "1234"}}
{"_user": {"email": "sammy#mail.com", "password": "1234"}}
{"_user": {"email": "tommy#mail.com", "password": "1234"}}
{"_user": {"email": "tommy#mail.ae", "password": "1234567"}}
{"_user": {"email": "hot#mail.com", "password": "1234567"}}
The error mentioned above was sent back on the last request as the email hot#mail.com is repeated.
If you view the link http://mongoosejs.com/docs/api.html#schematype_SchemaType-unique , you'll see that the E11000 error is only sent when the email entered is not unique. Moreover, your email can't be an empty string or not be present as that violates the required property.
ES6:
const userSchema = new Schema({
name: String,
id: {
type: String,
required: true,
unique: true,
validate: async (value) => {
try {
const result = await userModel.findOne({ id: value })
if (result) throw new Error("duplicity detected: id :" + value);
} catch (error) {
throw new Error(error);
}
}
}
})
const userModel = mongoose.model<Document>('users', userSchema);
ES6 (TypeScript):
const userSchema = new Schema({
name: String,
id: {
type: String,
required: true,
unique: true,
validate: async (value: any): Promise<any> => {
try {
const result: Document | null = await userModel.findOne({ id: value })
if (result) throw new Error("duplicity detected: id :" + value);
} catch (error) {
throw new Error(error);
}
}
}
})
const userModel: Model<Document, {}> = mongoose.model<Document>('users', userSchema);
In your user schema set attribute email as unique (unique: true).
var userSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true}, });

Packing data with mongoose

I have 3 files with different schema. User has many notebooks and notebooks has many notes. Example of schemas :
UserSchema:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var User = new Schema({
username: { type: String, require: true, index: { unique: true }, trim: true},
password: { type: String, require: true, select: true },
age: { type: Number, min: 0 },
firstname: String,
secondname: String,
token: String,
role: String,
city: String,
rememberMe: Boolean
});
module.exports = mongoose.model('User', User);
NotebookSchema:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
Note = require('./note'),
User = require('./user');
var NoteBook = new Schema({
creator: { type:Schema.ObjectId, ref:"User"},
name: String,
description: String
});
NoteBook.methods.getAllNotes = function(cb) {
Note.find({notebook: this}, function(err, noteList){
cb(noteList);
});
};
module.exports = mongoose.model('NoteBook', NoteBook);
NoteSchema:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var NoteSchema = new Schema({
notebook: { type: Schema.Types.ObjectId, ref: 'NoteBook'},
name: String,
description: String,
content: String
});
module.exports = mongoose.model('Note', NoteSchema);
I get in request userId and I need to pack json all this line of data. User with Notebooks and Notebooks with note in one json. I triyed something like this:
function getTree(req, res) {
var data = [];
User.findOne({_id: req.body.userId}, function(err, user) {
NoteBook.find({creator: user._id}, function(err, notebookList) {
for (var idx in notebookList) {
Note.find({notebok: notebookList[idx]._id}, function(err, noteList) {
var children = [];
for (var noteIdx in noteList) {
children.push({
'text': noteList[idx].name,
'a_attr' : {
'data-node-type': 'note',
'data-node-id': noteList[idx]._id,
},
});
}
data.push({
'text': notebookList[idx].name,
'a_attr' : {
'data-node-type': 'notebook',
'data-node-id': notebookList[idx]._id,
},
'children': children
});
});
}
res.json({ tree: data });
});
});
}
but it doesn't work.
var async = require("async");
function getTree(req, res) {
var data = [];
User.findOne({_id: req.body.userId}, function(err, user) {
NoteBook.find({creator: user._id}, function(err, notebookList) {
async.forEach(notebookList, function(notebook, callback){
Note.find({notebok: notebook._id}, function(err, noteList) {
var children = [];
for (var noteIdx in noteList) {
children.push({
'text': noteList[idx].name,
'a_attr' : {
'data-node-type': 'note',
'data-node-id': noteList[idx]._id,
},
});
}
data.push({
'text': notebookList[idx].name,
'a_attr' : {
'data-node-type': 'notebook',
'data-node-id': notebook._id,
},
'children': children
});
});
}, function(err){
res.json({ tree: data });
});
});
});
}

Resources