Allow users to add items to their profiles Mongoose - angularjs

I am building a mean stack app with express and mongoose. I have two schemas, userSchema and courseSchema:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var courseSchema = mongoose.Schema({
title:{type:String, required:'{PATH} is required!'},
featured:{type:Boolean, required:'{PATH} is required!'},
published:{type:Date, required:'{PATH} is required!'},
courseLink:{type:String, required:'{PATH} is required!'},
user: [{type:Schema.Types.ObjectId, ref : 'User'}]
});
var Course = mongoose.model('Course', courseSchema);
module.exports = Course;
var userSchema = mongoose.Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
username: {
type: String,
required: true,
unique: true // creates unique index inside MongoDB
},
salt: {type: String, required: true},
hashed_pwd: {type: String, required: true},
roles:[String],
courses:[{type: Schema.ObjectId,
ref: 'Course' }]
});
I am able to create users and and courses (as an admin). What I want to do now is to allow each user add a course to his list of courses (or just click a 'like' button beside the course and that course would be added to his profile).
On the side of the controller, I have tried to check for the user id from the session, find that user and add the course to his document. But that's where I am stuck,
exports.addMyCourse = function(req, res){
console.log('user id', req.session.passport.user);
console.log('id', req.body._id);
var currentUserId = req.session.passport.user;
User.findOne({'_id':currentUserId}, function(err, doc){
console.log(doc);
});
Most of the solutions I looked at are not very clear about this. Any help would be appreciated.

RESOLVED:
I used $addToSet to add the course objects into the courses array inside the User model:
This might be useful for people searching for similar soutions:
My User schema:
var userSchema = mongoose.Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
username: {
type: String,
required: true,
unique: true // creates unique index inside MongoDB
},
salt: {type: String, required: true},
hashed_pwd: {type: String, required: true},
roles:[String],
courses:[{
type:Schema.ObjectId, ref:'Course'
}]
});
var User = mongoose.model('User', userSchema);
My Course schema:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var courseSchema = mongoose.Schema({
title:{type:String, required:'{PATH} is required!'},
featured:{type:Boolean, required:'{PATH} is required!'},
published:{type:Date, required:'{PATH} is required!'},
courseLink:{type:String, required:'{PATH} is required!'}
});
var Course = mongoose.model('Course', courseSchema);
Inside my controllers folder, I have users.js and courses.js:
In the courses.js file, I created the addMyCourses middleware to update the User model's courses array by first retrieving the current user's id from the session and using $addToSet to insert the object and avoid duplicates at the same time. Also I made sure I am adding only the ObjectId's of the courses and not the entire course document so I won't have future problems with too much data in one document:
exports.addMyCourse = function(req, res){
var myCourse = {
title: req.body.title,
featured: req.body.featured,
published: req.body.published,
courseLink: req.body.courseLink
};
var currentUserId = req.session.passport.user;
var courseId = req.body._id;
User.update({_id:currentUserId},
{$addToSet: {"courses": courseId}},
{safe: true, upsert: true, new : true},
function(err, model) {
console.log(model);
}
);
};
Since I only had the ObjectId's of the courses inside the courses array of the User model, I had to use mongoose's populate() method to do a joint query on both models so that I get the corresponding course documents of the ids.
In users.js file:
exports.getUserCourses = function(req, res, next){
var currentUserId = req.session.passport.user;
User.findById(currentUserId).populate('courses')
.exec(function(err, data){
if(err) {
console.log(err);
}
console.log('user courses', data);
res.send(data);
})
};

Related

Mongo db showing record after deleting

I have an Angular on the frontend with node on the backend, where I show user messages that a user can delete and edit.
When I am deleting a message I also remove all the records from the users array of messages, and on the frontend that works fine, no messages that were deleted show up, but when I check in the DB, for user records, there is still one recored in the messages array of a user.
So, when I do db.users.find()
I get for the user that has all messages deleted:
"messages" : [ ObjectId("58d921cacca7c04abd100344") ], "__v" : 9
This is the messages model where I pull the message record on delete from the DB.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user');
var schema = new Schema({
content: {type: String, required: true},
user: {type: Schema.Types.ObjectId, ref: 'User'}
});
schema.post('remove', function (message) {
User.findById(message.user, function (err, user) {
user.messages.pull(message);
user.save();
});
});
module.exports = mongoose.model('Message', schema);
And this is the user model:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongooseUniqueValidator = require('mongoose-unique-validator');
var schema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
password: {type: String, required: true},
email: {type: String, required: true, unique: true},
messages: [{type: Schema.Types.ObjectId, ref: 'Message'}]
});
schema.plugin(mongooseUniqueValidator);
module.exports = mongoose.model('User', schema);
When I check the messages collection, there are no messages there at all.
Though it works fine on the frontend, I wonder why is it still showing that record in the DB, when all the messages have been deleted for the user?

Mongoose how to save document inside an array

I have a model which looks like this:
User.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var memberSchema = new Schema({
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true,
min: 8
}
});
var userSchemaPrimary = new Schema({
team_code : {
type: String,
required: true,
unique: true
},
members:[memberSchema],
});
var User = mongoose.model('User', userSchemaPrimary);
module.exports = User;
And this is how am trying to save
var User = require('../models/user');
var newTeam = new User({
team_code : 'CODE01',
members:
{
email: req.body.email,
password: pass
}
});
newTeam.save(function(err) {
if (err) throw err;
console.log('User saved successfully!');
return res.send("Done");
});
When executed, throws model validation error.
Well I tried to save data without the array documents, then its saves successfully. But when I try to save the array (array "members"), it throws validation error.
I WANT TO
Store data in the following way:
{
team_code: "CODE01",
members: [
{
email: "test01#email.com",
password: "11111111"
},
{
email: "test02#email.com",
password: "22222222"
}
{
email: "test03#email.com",
password: "33333333"
}
]
}
I dont understand what is going wrong. Any help is appreciated.
You are assigning object to members field, but it's an array
var newTeam = new User({
team_code : 'CODE01',
members: [{
email: req.body.email,
password: pass
}] // <-- note the array braces []
});

MongoDB Reference Issue

I have two collections set up at the moment. One collection lists all of the products in my store. The other collection stores the ratings on a scale of 1-5. The ratings store in the ratings collection successfully, and the products are stored and listed successfully. However, I am attempting to reference the appropriate rating for the individual product that is listed. I am using an ng-repeat to list all of the products in my product database. I'm not sure what is going on, but my reference to the ratings is returning an empty array.
How can I get the ratings to show for each product?
Product Schema:
var mongoose = require('mongoose');
var productSchema = new mongoose.Schema({
title: {
type: String,
unique: true,
required: true,
index: true
},
description: {
type: String,
required: true
},
price: {
type: Number,
required: true,
min: 0,
},
rating: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Rating'
}],
image: {
type: String,
required: true
}
});
module.exports = mongoose.model('Product', productSchema);
Product Controller (just the read portion):
var Product = require('../models/Product');
module.exports = {
read: function (req, res) {
Product.find(req.query)
.populate('Rating')
.exec(function (err, result) {
if (err) { return res.status(500).send(err);}
console.log("this is in the product ctrl", result);
{res.send(result);}
});
},
};
Rating Schema:
var mongoose = require('mongoose');
var ratingSchema = new mongoose.Schema({
rating: {
type: Number,
enum: [1, 2, 3, 4, 5]
}
});
module.exports = mongoose.model('Rating', ratingSchema);
Rating Controller (just read and create shown):
var Rating = require('../models/Rating');
module.exports = {
create: function (req, res) {
var newRating = new Rating(req.body);
newRating.save(function (err, result) {
if (err) return res.status(500).send(err);
else res.send(result);
});
},
read: function (req, res) {
Rating.find(req.query)
.populate('type')
.exec(function (err, result) {
if (err) return res.status(500).send(err);
else res.send(result);
});
}
};
Screenshot of view:
If more information is needed please let me know. I thought that something may be wrong with my .populate, but after reading this documentation I think everything is good. I'm stumped.
http://mongoosejs.com/docs/populate.html

How can I push element to array in http.put in angularjs?

I have the following schema:
var UserSchema = new Schema({
name: String,
email: { type: String, lowercase: true },
projects: [{type: Schema.ObjectId, ref:'Project'}],
//....
}
How can I add projectId by using http.put?
This is among the things that I have tried:
$http.put('/api/users/'+User._id, {'projects': project._id});
Solved it using:
$http.put('/api/users/'+User._id, {'projects': User.projects});
and in my update method:
_.extend(user, req.body);
instead of
_.merge(user, req.body);

How to query mongoose by property that is and array item

I have a mongoose model that looks like this:
var mongoose = require('mongoose')
, Schema = mongoose.Schema;
var PictureSchema = new Schema({
listId: { type: Array, required: true },
thumb: { type: String, required: true },
large: { type: String, required: true }
});
var Picture = module.exports = mongoose.model('Picture', PictureSchema);
I am trying to update instances of this model in my router by looking up a Picture via the "listId" property. Like this:
app.put('/pictures/append', function(req, res) {
var targetListId = req.body.targetListId
, currentListId = req.body.currentListId;
Picture
.find({ listId: currentListId }, function (err, picture) {
console.log('found pic', picture);
picture.listId.push(targetListId);
picture.save(function(err, pic) {
console.log('pic SAVED', pic);
});
});
});
"currentListId" is a string, and listId is an array of currentListId's. Maybe this isn't the correct way to query a a property that is an array?
I am getting an error:
TypeError: Cannot call method 'push' of undefined
On the line:
picture.listId.push(targetListId);
But when I look up the picture models in mongo, they DO have listId arrays and some DO contain the item "currentListId" that I am using for my query.
I tried using $elemMatch and $in but I don't know if I was using them correctly.
Any idea if I am just writing my query wrong?
Specifying an Array typed field in your schema is equivalent to Mixed which tells Mongoose that field could contain anything. Instead, change your schema to something like this:
var PictureSchema = new Schema({
listId: [String],
thumb: { type: String, required: true },
large: { type: String, required: true }
});

Resources