MeanJS MongoDb insert issue - node.js

I'm creating an application using MEANJS. I've a mongoose schema defined like this:
var UserdetailSchema = new Schema({
fullName: {
type: String,
trim: true
},
userName: {
type: String,
trim: true
},
mobile: {
type: String,
default: '',
trim: true
},
address: {
type: String,
trim: true
},
suburb: {
type: String
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
mongoose.model('Userdetail', UserdetailSchema);
What I'm trying to achieve is after login user is redirected to edit view to update rest of the info like "mobile, suburb, address" etc which is in userdetails schema.
This is my controller. I've changed default create() method to the following: I'm redirecting to the edit it as soon as the first step of inserting is complete.
// Create new Userdetail for current user
function create(FullName,UserName) {
// Create new Userdetail object
var userdetail = new Userdetails ({
fullName: FullName,
userName: UserName
});
// Redirect after save
userdetail.$save(function(response) {
$location.path('userdetails/' + response._id+'/edit');
console.log(response._id);
// Clear form fields
//$scope.name = '';
}, function(errorResponse) {
console.log(errorResponse.data.message);
$scope.error = errorResponse.data.message;
});
};
To create a user details I'm only inserting fullName, and userName as a first step and updating it later.
issue is, it is only allowing me 1 userdetails to insert and if I try to insert another userdetails of another user. it gives an error "Name already exists", though there is no name in the schema.
Server side code to create userdetails
/**
* Create a Userdetail
*/
exports.create = function(req, res) {
var userdetail = new Userdetail(req.body);
userdetail.user = req.user;
userdetail.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
res.jsonp(userdetail);
}
});
};

I got it working after droping my collection "userdetails" from shell and trying inserting again. I followed this link Mongodb- Add unique index on an existing collection . It was more of MongoDB issue.

Related

mongoose model.create() is not allowing duplicate inputs without any key in model being `'unique:'true'`

I am using mongoose along with nodejs to insert data. I am using MVC and in my controller I have this code:
module.exports.create_tracsaction = function (req, res) {
Company.findOne({ username: req.body.req_from }, function (err, user) {
if (user.vaccine.extra < req.body.req_vac) {
return res.redirect('/vaccine');
}
else {
var data = {
req_from: req.body.req_from,
req_to: req.body.req_to,
amt_req: req.body.req_vac,
transaction_status: "Awaiting confirmation",
vaccine: user.vaccine.name,
transaction_value: user.vaccine.price * req.body.req_vac
}
Transaction.create(data);
return res.redirect('/vaccine');
}
})
console.log(req.body);
};
This is my schema
const transactionSchema = new mongoose.Schema({
req_from: {
type: String,
required: true
},
req_to: {
type: String,
required: true
},
amt_req: {
type: Number,
required:true
},
transaction_status: {
type: String,
default: "Awaiting confirmation"
},
vaccine: String,
transaction_value: Number
}, {
timestamps: true
});
Even though non of the fields have property unique:'true', I am getting this error:
MongoError: E11000 duplicate key error collection: innovate_dev.transactions index: username_1 dup key: { username: null }
How to remove this error? The first time I sent data from views there was no error but from thereafter it's giving this error every time.
Let me know if you need anything else. Thanks in advance :D
It looks like a unique index got created at some point on the username field of transactions. That according your schema, it no longer exists. Thus every time you make an entry null is being indexed and throwing an error.
If you are using Compass or another GUI you can go in and delete it.
Otherwise to remove with MongoShell:
use innovate_dev
It will switch to your db
db.transactions.dropIndex('username_1')

How to get the newly created embedded document with Mongoose?

I have a schema with embedded documents, the setup looks like this:
var Guests = new Schema({
email: {
type: String,
required: true
},
time: {
type: Date,
default: Date.now
}
});
var Devices = new Schema({
user: {
type: String,
required: true
},
time: {
type: Date,
default: Date.now
},
name: {
type: String,
required: true
},
guests: [Guests]
});
I create a new guest with the following code:
// Check if already invited
Device.findOne({ '_id': req.body.device_id, 'user': req.user.href, 'guests.email': req.body.guest_email }, function (err, guest) {
// Check for error
if (err) return handleError(err);
// If already invited
if (guest) {
return res.status(402).send({code: 'already_invited', message: 'This guests is already invited.'});
} else {
// If not invited yet, lets create the new guest
device.guests.push({
"email": req.body.guest_email
});
// Save the new guest to device
device.save(function (err) {
if (err) res.status(400).send(err);
// Get the saved guest ID, but how?
});
}
});
Everything works, but i don't know how to get the newly created embedded guest document. I especially need the ID, but i want the whole new guest in my response. Inside the device.save function, device.guests already has the ID of the newly created record, so i could loop through it and find it that way, but i'm wondering if theres an easier way to do it.
device.save(function (device, err) {
if (err) res.status(400).send(err);
// use device here. i.e res.status(200).json(device);
});
If you actually create a Guests entity with the new operator, the _id property will be populated. Try something like this:
var guest = new Guests({guest_email: "foo"});
device.guests.push(guest);

Where to place email validator within project?

I am on day 2 of learning node and Java Script. I have been following basic tutorials and decided to attempt and implement simple email validation into my code.
The problem is i am not sure where to place the code - i have a server.js file that holds all of the CRUD operations and a Mongoose model that which ensures the correct data is entered. Does anyone have any advice as to the best way to validate a user-entered email using this module?
//Email-validation npm module
var validator = require("email-validator");
validator.validate("test#email.com");
//Mongoose model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Tickets = new Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
address: {
type: String,
required: true
},
price: {
type: Number,
required: true,
min: 1,
max: 100
}
});
module.exports = mongoose.model('Ticket', TicketSchema);
Validate email before saving object. Code should look something like this:
Tickets.pre('save', function (next) {
var ticket = this;
if (!ticket.isModified('email')) {
next();
} else {
var valid = validator.validate(ticket.email);
if(valid) {
next();
} else {
next(valid);
}
}
});

Mongoose - trying to do 'JOINS' in MEAN stack

I am having a hard time understanding the async nature of NodeJS.
So, I have an articles object with this schema:
var ArticleSchema = new Schema({
created: {
type: Date,
default: Date.now
},
title: {
type: String,
default: '',
trim: true,
required: 'Title cannot be blank'
},
content: {
type: String,
default: '',
trim: true
},
creator: {
type: Schema.ObjectId,
ref: 'User'
}
});
and the User schema is:
var UserSchema = new Schema({
firstName: String,
lastName: String,
...
});
The problem is when I query for all the documents like so:
exports.list = function(req, res) {
// Use the model 'find' method to get a list of articles
Article.find().sort('-created').populate('creator', 'firstName lastName fullName').exec(function(err, articles) {
if (err) {
// If an error occurs send the error message
return res.status(400).send({
message: getErrorMessage(err)
});
} else {
// Send a JSON representation of the article
res.json(articles);
}
});
};
I get all the articles back successfully, but for some reasons, the article creator is returning different results
for locally authenticated users (localStrategy) and facebook authenticated users (facebook strategy) for locally authenticated users, I get:
articles = {
creator: {
id: 123,
firstName: 'Jason',
lastName: 'Dinh'
},
...
}
for fb authenticated users, I get:
articles = {
creator: {
id: 123
},
...
}
I can't seem to get a grip on PassportJS API, so what I want to do is
iterate through articles and for each article, find the user document using the article creator ID and add the user firstName and lastName to the articles object:
for each article in articles {
User.findOne({ '_id': articles[i].creator._id }, function(err, person){
//add user firstName and lastName to article
});
}
res.json(articles);
You can probably already see the problem here... my loop finishes before the documents are returned.
Now, I know that MongoDB doesn't have any 'joins' and what I want to do is essentially return a query that 'joins' two collections. I think I'm running into problems because I don't fundamentally understand the async nature of
node.
Any help?
You can use find instead of findOne and iterate inside your callback function.
User.find({ }, function(err, personList){
for each person in personList {
for each article in articles {
if (person._id === article.creator._id) {
//add user firstName and lastName to article
}
}
}
res.json(articles);
});
UPDATE:
Considering the scenario that #roco-ctz proposed (10M users), you could set a count variable and wait for it to be equal to articles.length:
var count = 0;
for each article in articles {
User.findOne({ '_id': articles[i].creator._id }, function(err, person){
//add user firstName and lastName to article
count += 1;
});
}
while (count < articles.length) {
continue;
}
res.json(articles);

How to parse request (or end points) to query mongoose

I am going to to implement a web api like this
POST /groups/:groupname/chats/:chatType
There could be several groups and each group has at most two chats, a private one or a public one.
Currently, in my /models directory, two related schemas look like this:
// group.js
...
var groupSchema = new mongoose.Schema({
groupname: {type: String, required: true, index:{unique: true}},
privateChat: {type: mongoose.Schema.Types.ObjectId, ref: 'Chat'},
publicChat: {type: mongoose.Schema.Types.ObjectId, ref: 'Chat'}
});
module.exports = mongoose.model('Group', groupSchema)
// chat.js
var chatSchema = new mongoose.Schema({
chatType: String, // public or private
message: [{text: String}]
});
module.exports = mongoose.model('Chat', chatSchema);
So the question is how can I post a message like "Hello World!" to
/groups/boygroup/chats/private
...
I have finished the request GET /groups/:groupname by findOne() method like this:
router.get('/groups/:groupname', function(req, res) {
var groupname = req.body.groupname || req.params.groupname;
Group.findOne({
groupname: groupname
}, function(err, group) {
if (err)
return next(err);
if (!group) {
res.status(404).send({
success: false,
message: "group not found"
});
} else {
res.json(group);
}
});
});
But I have no idea how to get to a specific chat in a specific group. Maybe my mongoose schema is not good.
Any suggestion is appreciated.

Resources