Create an association through a single form Mongoose/express - node.js

Through a single form I'm trying to build a game object that consists of a 'game_name', and a 'game_length', and a ref association by ObjectId to a 'player'. What I have is building both objects but the player is not being saved in the players array in the Game model. Thanks for any help in advance.
Schema and Models
Game Schema/Model
var gameSchema = new mongoose.Schema({
course_name: String,
game_length: Number,
players: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Game'
}],
created: {type: Date, default: Date.now}
})
var Game = mongoose.model('Game', gameSchema);
Player Schema/Model
var playerSchema = new mongoose.Schema({
player_name: String,
})
var Player = mongoose.model('Player', playerSchema);
Post Route
app.post('/games', function(req, res){
Game.create(req.body.game, function(err, newGame){
if (err) console.log(err);
Player.create(req.body.player, function(err, newPlayer){
if (err) console.log(err);
newGame.players.push(newPlayer);
})
res.redirect('games');
})
})

It looks like you just need to call .save:
app.post('/games', function(req, res){
Game.create(req.body.game, function(err, newGame){
if (err) console.log(err);
Player.create(req.body.player, function(err, newPlayer){
if (err) console.log(err);
newGame.players.push(newPlayer);
newGame.save(function(err) {
if (err) return console.log(err);
// saved!
res.redirect('games');
});
})
})
})

Related

Object.assign() Issues on Mongoose SubDocument Schema

So when I use Object.assign, (ex. Object.assign({foo:bar1},{foo:bar2}) on a particular Mongoose Subdocument Schema, the foo:bar2 obj won't overwrite the foo:bar1 obj.
In my app I have an Account Schema with two sub-document schemas, Projects & Properties. It's in the Project sub document schema that I encounter the issue.
Here are my Models:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ProjectSchema = new Schema({
_id: String,
name: String,
}, { strict: false })
var PropertySchema = new Schema({
_id: String,
slug: String,
name: String,
type: String,
placeholder: String,
order: Number
}, { strict: false })
var AccountSchema = new Schema({
_id: String,
name: String,
slug: String,
email: String,
properties: [PropertySchema],
projects: [ProjectSchema],
}, { strict: false })
module.exports = mongoose.model('Account', AccountSchema);
Here is a snippet of my Middleware(I think that's what it's called, please correct me if I am wrong). This is where I do the Object.assign to overwrite the particular projects' properties. If it helps I can post all the routes.
router.route('/accounts/:account_id/projects/:project_id')
.get(function(req, res) {
Project.findById(req.params.project_id, function(err, project){
if (err)
res.send(err);
res.json(project);
});
})
.delete(function(req, res){
Account.findById(req.params.account_id, function(err,account){
if (err)
res.send(err);
account.projects.id(req.params.project_id).remove();
account.save(function(err) {
if(err)
res.send(err);
res.json({message: 'Project Deleted'});
});
})
})
.put(function(req, res){
Account.findById(req.params.account_id, function(err,account){
if (err)
res.send(err);
Object.assign(account.projects.id(req.params.project_id), req.body);
account.save(function(err) {
if(err)
res.send(err);
res.json({message: 'Project Updated'});
});
})
});
// ----------------------------------------------------
router.route('/accounts/:account_id/properties/:property_id')
.get(function(req, res) {
Property.findById(req.params.property_id, function(err, property){
if(err)
res.send(err);
res.json(property);
});
})
.delete(function(req, res){
Account.findById(req.params.account_id, function(err, account){
if (err)
res.send(err);
account.properties.id(req.params.property_id).remove();
account.save(function(err){
if(err)
res.send(err);
res.json({ message: 'Successfully Deleted' });
})
})
})
.put(function(req, res){
Account.findById(req.params.account_id, function(err, account) {
if (err)
res.send(err);
Object.assign(account.properties.id(req.params.property_id), req.body);
account.save(function(err) {
if(err)
res.send(err);
res.json({message: 'Property Updated'});
})
})
});
So it's the Put Method that is giving me the issue, I can Get, Post, Delete with no issues, but the Put part for Projects is where I encounter this Object.assign issue. Funny thing is that everything works perfectly for the Property Schema Put Method, and it is basically the exact same as the Project one.
If I console.log some of the values in the Project's Put Method I get the following:
console.log(account.projects.id(req.params.project_id));
//original value logs { _id: '1486609836741', foo: 'bar' }
console.log(req.body);
//updated value logs { foo: 'barred', _id: '1486609836741' }
console.log(Object.assign(account.projects.id(req.params.project_id), req.body));
//logs the original value { _id: '1486609836741', foo: 'bar' }
So when I log the updated and original values they have equal keys, shouldn't the Object.assign work? Is the original Obj more complex then what the console.log displays, and maybe the original and updated don't have equal keys?
I am kinda stumped, any help would be greatly appreciated. Let me know if I need to post more of my code. Thanks.
Object.assign(account.projects.id(req.params.project_id), req.body);
Here, you are trying to assign to an object that is result of MongooseDocumentArray.id method call on account.projects array. Which will affect just a copy of document which is returned by function, and won't affect the original array of subdocuments.
I am new to Mongoose, but I'll suggest you trying to work with account.projects as with MongooseArray:
var project = account.projects.id( req.params.project_id ),
index = account.projects.indexOf( project );
Object.assign( account.projects[ index ], req.body);

Removing a child element in subdocument not working

I'm fairly new to Mongoose and don't think my approach on deleting an item in a subdocument is the right one.
I have the following schema setup:
//DEPENDENCIES
var mongoose = require('mongoose');
var contactSchema = new mongoose.Schema({
name:{type:String},
age:{type:Number}
});
var phoneSchema = new mongoose.Schema({
number:{ type: String },
phoneType:{ type: Number }
})
var memberSchema = new mongoose.Schema({
firstname: {
type: String
},
lastname: {
type: String
},
phone:[phoneSchema],
contacts:[contactSchema]
});
//RETURN MODEL
module.exports = mongoose.model('member', memberSchema);
To remove an item from the phone, in my Express API, I first find the parent then reference "remove" for the child ID, like this. But it does not work.
router.route('/owner/:ownerId/phone/:phoneId')
.delete(function(req, res){
Member.findOne({_id: req.body.ownerId}, function(err, member){
member.phone.remove({_id: req.body.phoneId}, function(err){
if(err)
res.send(err)
res.json({message: 'Success! Phone has been removed.'})
});
});
});
Figured out that I was looking for req.body and was actually needing req.params.
Also found right syntax on Mongoose docs:
router.route('/owner/:ownerId/phone/:phoneId')
.delete(function(req, res){
Member.findOne({_id: req.params.ownerId}, function(err, member){
member.phone.id(req.params.phoneId).remove();
member.save(function (err) {
if (err) return handleError(err);
console.log('the sub-doc was removed');
});
});
});

How to use object id that give reference in nodejs mongodb

There is no another error but I want to know just one thing.How to use that give reference in User schema object _id it means location_id how to use when I add new User.
User Schema :
var userSchema = Mongoose.Schema({
name:{type: String,require:true},
surname: {type: String,require:true},
tel: {type: String,require:true},
age: {type: String,require:true},
mevki_id: {type: String,require:true},
location_id: { type: Mongoose.Schema.Types.ObjectId, ref: 'locations' }
});
Location schema:
var LocationSchema = Mongoose.Schema ({
il: {type: String, require:true},
ilce: {type:String, require:true}
});
UserController -- I add user here
this.createUser = function(req, res) {
var la=new Location({il:'istanbul',ilce:'camlica',location_id:la._id}).save(function (err) {
if (err) return handleError(err);
});
var user = new User({
name:'akif',surname:'demirezen',tel:'544525',age:'45',mevki_id:'2',
}).save(function (err) {
if (err) return handleError(err);
res.send(JSON.stringify(job));
});
}
There are several errors in your code. For example, the require property should be required.
Other problem is that you are setting the location_id value of la with a reference to la, that at that time has not been yet assigned a value.
Mongo will automatically create a field called _id: ObjectId on all your objects. Try this:
this.createUser = function(req, res) {
var la = new Location({
il:'istanbul',
ilce:'camlica',
}).save(function (err, location) {
if (err) return handleError(err);
var user = new User({
name:'akif',
surname:'demirezen',
tel:'544525',
age:'45',
mevki_id:'2',
location_id: location._id
}).save(function (err, user) {
if (err) return handleError(err);
// Warning: AFAIK job does not exist, should it be user?
res.send(JSON.stringify(job));
});
});
}

Update nested array with Express and Mongoose

I have an Express application with Mongoose. I have a model
var AttendeeSchema = new Schema({
name: String,
registered: Boolean
});
var EventSchema = new Schema({
name: String,
description: String,
attendees : [AttendeeSchema],
created: { type: Date, default: Date.now },
updated: { type: Date, default: Date.now }
});
The code for creating an event is:
router.route('/:event_id')
.get(function(req, res) {
Event.findById(req.params.event_id, function(err, event) {
if (err)
res.send(err);
res.json(event);
});
})
.put(function(req, res) {
Event.findById(req.params.event_id, function(err, event) {
if (err)
res.send(err);
event.name = req.body.name;
event.description = req.body.description;
event.attendees: req.body.attendees;
event.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Event updated successfully!' });
});
});
})
The code for updating an event is:
router.route('/:event_id')
.put(function(req, res) {
Event.findById(req.params.event_id, function(err, event) {
if (err)
res.send(err);
event.name = req.body.name;
event.description = req.body.description;
event.attendees: req.body.attendees;
event.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Event updated successfully!' });
});
});
})
The problem is that events are being created successfully however when I try to update an event, it only updates the event name and description, but not changes to the attendees name or registered status. I also noticed that the version is not updated from "__v0" to "__v1"
Anyone some hints as to why I cannot update attendee specific information with the above code?
It looks like you need a = where you have a : ;)
event.attendees: req.body.attendees;

Best practice for structuring Express routes that handle MongoDB queries

I am building a RESTful service for querying a movie database using
Express.js, Node.js and MongoDB and I am a beginner on all of them.
My question is what is the best practice for structuring db queries with Node so that I take advantage of the callback mechanisms and not block the server but at the same time not write bloated code.
I modified the code provided by the express-generator and I think it achieves the former but not the latter. What are your comments?
If you could provide a general skeleton for an Express route that handles db queries, I would appreciate it.
Below is my code
var findMovie = function(db, callback, req, res) {
var path = req.path.split("\/");
var cursor = db.collection('movies').find({"_id" : ObjectId(path[path.length - 2])});
var query = [];
cursor.each(function(err, doc) {
assert.equal(err, null);
if (doc != null) {
query.push(doc);
} else {
res.json(query);
callback();
}
});
}
router.get('/movies/:id/info/', function(req, res, next){
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
findMovie(db, function() {
db.close();
}, req, res);
});
});
First if you use mongoDB in node i will definately recommend to use mongoose or some other object modeling tool, its much easier than native driver.
then it might look like this:
/model/user.js
var mongoose = require('mongoose');
var UserSchema = new mongoose.Schema({
createdAt: {type: Date, default: Date.now},
updatedAt: {type: Date, default: Date.now},
email: {type: String, unique: true, required: true},
password: {type: String, required: true},
active: {type: Boolean, default: true},
role: {type: String, default: 'user'},
accessLevel: {type: Number, default: 1}
}, {
collection: 'users'
});
module.exports = mongoose.model('User', UserSchema);
/controllers/users.js
var User = require('../model/user');
exports.create (req, res, next) {
var newUser = new User(req.body);
newUser.save(function (err) {
if (err)
return next(err);
res.json({
message: 'User created'
});
});
}
exports.listAll (req, res, next) {
User.find({}, function (err, users) {
if (err)
return next(err);
res.json(users)
});
}
exports.getById (req, res, next) {
User.findById(req.params.id, function (err, user) {
if (err)
return next(err);
res.json(user)
});
}
/routes/users.js
var controller = require('../controllers/users');
var router = require('express').Router();
router.route('/users')
.post(controller.create)
.get(controller.listAll)
router.route('/users/:id')
.get(controller.getById)
.delete(controller.remove)

Resources