Mongoose how to save document inside an array - arrays

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 []
});

Related

Allow users to add items to their profiles Mongoose

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);
})
};

location object expected, location array not in correct format

I have spent doing such a straight forward thing. I just want to do a CRUD operation on a user model using nodejs, mongoose, restify stack. My mongo instance is on mongolab.
The user should contain a "loc" field . User schema is as follows :
var mongoose = require('mongoose')
var Schema = mongoose.Schema;
var userSchema = new Schema( {
email_id : { type: String, unique: true },
password: { type: String},
first_name: String,
last_name: String,
age: String,
phone_number: String,
profile_picture: String,
loc: {
type: {},
coordinates: [Number]
}
});
userSchema.index({loc:'2d'});
var User = mongoose.model('user', userSchema);
module.exports = User;
the rest api used to post is as follows :
create_user : function (req, res, next) {
var coords = [];
coords[0] = req.query.longitude;
coords[1] = req.query.latitude;
var user = new User(
{
email_id : req.params.email_id,
password: req.params.password,
first_name: req.params.first_name,
last_name: req.params.last_name,
age: req.params.age,
phone_number: req.params.phone_number,
profile_picture: req.params.profile_picture,
loc: {
type:"Point",
coordinates: [1.0,2.0] // hardcoded just for demo
}
}
);
user.save(function(err){
if (err) {
res.send({'error' : err});
}
res.send(user);
});
return next();
},
Now when i do a POST call on curl -X POST http://localhost:3000/user --data "email_id=sdass#dfAadsfds&last_name=dass&age=28&phone_number=123456789&profile_picture=www.jakljf.com&longitude=1.0&latitude=2.0"
I get the following error
{
error: {
code: 16804
index: 0
errmsg: "insertDocument :: caused by :: 16804 location object expected, location array not in correct format"
op: {
email_id: "sdass#dfAadsfdsadkjhfasvadsS.com"
password: "sdass123DadakjhdfsfadfSF45"
first_name: "shaun"
last_name: "dass"
age: "28"
phone_number: "123456789"
profile_picture: "www.jakljf.com"
loc: {
coordinates: [2]
0: 1
1: 2
-
type: "Point"
}-
_id: "55efc95e0e4556191cd36e5e"
__v: 0
}-
}-
}
The location field is giving problems as the POST call works just fine if i remove the loc field from model
Below are the hits/trials I did :
1) Change userSchema.index({loc:'2d'}); to userSchema.index({loc:'2dsphere'});
2) Changing loc schema to everything given in Stackoverflow. I would like to know the right way to define this though.
3) Passing the hardcode 2d array but still it says Location object expected, location array not in correct format" what format is required for this ?
Any help in this regard is greatly appreciated. Thanks.
MongoDB 2d index requires the legacy coordinates pairs format, which is just an array of coordinates like [1, 2].
If you need GeoJSON support, please use the 2dsphere index.
userSchema.index({loc:'2dsphere'});
If you are using Spring Boot make sure you set the index type to 2DSphere:
#GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE) GeoJsonPoint location;

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);

mongoose update with push operations on array and set operation on object

I have this mongoose schema
var ContactSchema = module.exports = new mongoose.Schema({
name: {
type: String,
required: true
},
phone: {
type: Number,
required: true,
},
messages: [
{
title: {type: String, required: true},
msg: {type: String, required: true}
}],
address:{ city:String,
state:String
}
});
I have initially the collection set with name and phone field. I need to update the collection with new messages into messages array and new address into address object. the function must also need to handle any single operation, ie in some case i have only update to messages array or updates to both name and address. so how i can i do all operations in a single function.
var messages= {
title: req.body.title,
msg: req.body.msg
}
Model.findOneAndUpdate({'_id': req.body.id,},{$push: {messages:message}},{upsert: true}, function (err, data) {
if (err) {
return res.status(500).send(err);
}
if (!data) {
return res.status(404).end();
}
return res.status(200).send(data);
});
You could try use both the $set and $push operators in your update object. Suppose, for example, you want to update both name and address fields in one single operation, use the $set on the name field and a $push operation to the address array:
var messages= {
title: req.body.title,
msg: req.body.msg
},
query = {'_id': req.body.id},
update = {
$set: {name: req.body.name},
$push: {messages: message}
},
options = {upsert: true};
Model.findOneAndUpdate(query, update, options, function (err, data) {
if (err) {
return res.status(500).send(err);
}
if (!data) {
return res.status(404).end();
}
return res.status(200).send(data);
});

Properties with default values in Mongoose schema are not persisting

I have the following schema I've written using Mongoose:
var querySchema = mongoose.Schema({
quoteId: { type: String, default: '' },
zipcode: { type: String, default: '' },
email: { type: String, default: '' },
type: {type: String, default: ''},
isEmailChecked: { type: Boolean, default: true },
});
I provide values for only 3 properties in the querySchema assuming that the result of the fields will take default values when a new instance of query object is persisted:
var query = {};
query.quoteId = "1414775421426";
query.email = "myself#somewhere.com";
query.type = "Foo";
But following document is what I see as the result in the collection:
{
"_id" : ObjectId("5453c27d0e4c3f2837071856"),
"email" : "myself#somewhere.com",
"type" : "Foo",
"quoteId" : "1414775421426",
"__v" : 0
}
Should isEmailChecked and zipcode not be assigned their default values when a new instance of query object is persisted to the MongoDB database?
Following is how I am persisting an instance of the query object using ExpressJS/NodeJS:
app.post('/api/queries', function (req, res) {
QuoteQuery.create({
quoteId: req.body.query.quoteId,
type: req.body.query.type,
zipcode: req.body.query.zipcode,
email: req.body.query.email,
isEmailChecked: req.body.query.isEmailChecked,
}, function (err, query) {
if (err) {
res.send(err);
}
res.json(query);
});
});
Could somebody help me understand that why I got the isEmailChecked and zipcode properties in the resulting document in the MongoDB database?
I am using NodeJS, AngularJS and ExpressJS in my application along with MongoDB.
When you set mongoose model field it not use default value.
As workaround you can use underscore to extend mongoose model object with keys which exists in your query object like this:
_.extend(dbQueryObject, query);
Here is complete example:
var mongoose = require('mongoose');
var querySchema = mongoose.Schema({
quoteId: { type: String, default: '' },
zipcode: { type: String, default: '' },
email: { type: String, default: '' },
type: {type: String, default: ''},
isEmailChecked: { type: Boolean, default: true }
});
var db = mongoose.createConnection('mongodb://localhost:27017/stackoverflow',
{ server: { auto_reconnect: true } },
function(err) {
var QuerySchema = db.model('test', querySchema);
var query = {};
query.quoteId = "1414775421426";
query.email = "myself#somewhere.com";
query.type = "Foo";
QuerySchema.create({
quoteId: query.quoteId,
type: query.type,
zipcode: query.zipcode,
email: query.email,
isEmailChecked: query.isEmailChecked
}, function (err, query) {
process.exit(0);
});
});
Here is what in db:
{
"_id" : ObjectId("5453ce3c9f7e0d13c52abf61"),
"type" : "Foo",
"email" : "myself#somewhere.com",
"quoteId" : "1414775421426",
"__v" : 0
}

Resources