I'm trying to create a many to many relationship with mongoose for when I am creating an employee. However I'm getting the following error when I call the .post:
TypeError: Employee.create(...).populate is not a function
My .get in which I also use .populate isn't throwing any errors. Which makes me wonder why .post does.
This is my code:
app.route('/api/employees')
.get(function (req, res, next) {
Employee.find()
.populate('statuses')
.exec(function (err, employee) {
if (err) {
return next(err);
}
res.json(employee);
});
})
.post(function (req, res, next) {
Employee.create(req.body)
Employee.findById(req.params._id)
.populate('statuses')
.exec(function (err, employee) {
if (err) {
return next(err);
}
res.json(employee);
});
});
This is the status class:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var statusSchema = new Schema({
name: ['In office', 'Project', 'Fired', 'Resigned', 'Ill']
});
module.exports = mongoose.model('Statuses', statusSchema);
And this is the employee class:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var employeeSchema = new Schema({
name: String,
division: ['IT','System','Trainee','Intern'],
statuses: [{type:Schema.Types.ObjectId, ref: 'Statuses'}],
project: Boolean,
comment: {type:String, default:null}
});
module.exports = mongoose.model('Employees', employeeSchema);
It seems the .post also seems to throw a 500 error, but I'm not sure if the two are related.
Is there an obvious error in above code or should I look for a mistake somewhere else?
The first thing you did wrong in the post request is that you never save the state, if the state saved then you save the status._id in the statuses.Then you do findById and find the employee._id and then you populate.
Here is an example:
Status.create(req.body, (err, status) => {
if (err) console.error(`Error ${err}`)
Employee.create({
name: req.body.name,
comment: req.body.comment,
division: req.body.division,
name: status._id
}, (err, employee) => {
if (err) console.error(`Error ${err}`)
Employee
.findById(employee._id)
.populate('statuses')
.exec((err, employee) => {
if (err) console.error(`Error ${err}`)
// console.log(JSON.stringify(employee))
res.json(employee);
})
})
})
In mongoose is not possible to populate after creating the object.
see Docs
Related
Im trying to make an API with node JS (express and jwt) with a mongodb.
I've make some routes (like to get markers for example), that's working fine.
BUT i've also make a route in order to post some markers. When I query it (that takes long time, and with Postman), and I've an error like :
"Could not get any response"
and in my console :
Error: socket hang up
My route controller :
const model = require('../models/markers');
module.exports = {
create: function(req, res, next) {
model.create({
param_1: req.body.param_1,
param_2: req.body.param_2,
param_3: req.body.param_3,
}, function (err, result) {
if (err)
next(err);
else
res.json({status: "success", message: "Marker added successfully", data: null});
});
},
getAll: function(req, res, next) {
let list = [];
model.find({}, function(err, items){
if (err){
next(err);
} else{
for (let item of items) {
list.push({
id: item._id,
param_1: item.param_1,
param_2 : item.param_2,
param_3: item.param_3
});
}
res.json({status:"success", message: "Markers list found", data:{markers: list}});
}
});
},
};
And for my route :
const express = require('express');
const router = express.Router();
const markerController = require('../controllers/markers');
router.get('/', markerController.getAll);
router.post('/', markerController.create);
module.exports = router;
My model :
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const MarkerSchema = new Schema({
param_1: {
type: String,
required: true
},
param_2: {
type: String,
},
param_3: {
type: [{
type: String,
enum: ['0.5', '1', ',1.25', '1.5', '2', '3+']
}],
default: ['pending']
}
});
module.exports = mongoose.model('Marker', MarkerSchema);
My get router works fine but my post route don't.
You should check #Will Alexander comment, if it's a copy paste you have a typo in:
param_2: req.bodyparam_2,
I'm trying to write an endpoint for an API that will return all orders for a given user. My issue is that when I try to query the database using mongoose's findById function, the 'user' object is undefined in the callback function and I can't query the orders subdoc. To add to the confusion, I can get it to work if I don't use a callback function, but then I don't have proper error handling.
var mongoose = require('mongoose');
var router = express.Router();
var order_model = require('../models/order');
var user_model = require('../models/user');
router.get('/:userid/order/', function (req, res) {
// This works???
var u = user_model.findById(req.params.userid);
res.json(u.orders);
});
The following code throws the error "TypeError: Cannot read property 'orders' of undefined".
var mongoose = require('mongoose');
var router = express.Router();
var order_model = require('../models/order');
var user_model = require('../models/user');
router.get('/:userid/order/', function (req, res) {
// This throws an error.
user_model.findById(req.params.userid).then(function (err, user) {
if (err) {
res.send(err);
}
res.json(user.orders);
});
});
user.js
var mongoose = require('mongoose');
var ordersSchema = require('./order').schema;
var userSchema = new mongoose.Schema({
name: String,
email: String,
showroom: String,
orders: [ordersSchema]
});
module.exports = mongoose.model('User', userSchema);
order.js
var mongoose = require('mongoose');
var lineItemsSchema = require('./lineitem').schema;
var ordersSchema = new mongoose.Schema({
trackingNumber: Number,
lineItems: [lineItemsSchema]
});
module.exports = mongoose.model('Order', ordersSchema);
Any help / explanation of this behavior would be appreciated. Thanks!
The first parameter of the then callback is user, not err.
Either use a traditional callback:
user_model.findById(req.params.userid, function (err, user) {
if (err) {
res.send(err);
return; // Need to return here to not continue with non-error case
}
res.json(user.orders);
});
Or chain a call to catch on the promise to separately handle errors:
user_model.findById(req.params.userid).then(function (user) {
res.json(user.orders);
}).catch(function(err) {
res.send(err);
});
I usually query like this, it work perfect :
user_model.find(_id : req.params.userid)
.exec((err, user) => {
if(err){
//handle error
}
return res.status(200).json(user.orders);
})
});
I'm in the process of learning Node, Mongoose and Express by trying to build a CRUD API. When trying to "join" two MongoDB collections with the .populate function, I get an error that
db.collection(...).findOne(...).populate is not a function
My javascript chops are not great, so I've tried rewriting this in different ways to no avail.
server.js
require('./models/User')
require('./models/Product')
var db
mongodb.MongoClient.connect('mongodb://<username>:</password>#xxxx.mlab.com:xxx/xxx', (err, database) => {
if (err) return console.log(err)
db = database
app.listen(3000, function() {
console.log("listening on port 3000");
})
})
app.get('/api/users/:id', (req, res) => {
db.collection(USERS_COLLECTION).findOne({ id: (req.params.id) }).populate('product'), (err, doc) => {
if (err) handleError(res, err.message, 'Failed to get user')
res.status(200).json(doc)
console.log(req.params)
}
})
models/user.js
var mongoose = require('mongoose')
var UserSchema = new mongoose.Schema({
id: String,
first_name: String,
last_name: String
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Product'
}
})
mongoose.model('User', UserSchema)
Collections don't have the mongoose's model API including .populate. Instead of using collections directly, you should use the model that you registered in mongoose.
var schema = new mongoose.Schema(...);
var User = mongoose.model('User', schema);
// you can also get the model after it was registered via mongoose.model('User')
app.get('/api/users/:id', (req, res) => {
User.findOne({ id: (req.params.id) }).populate('product'), (err, doc) => {
if (err) handleError(res, err.message, 'Failed to get user')
res.status(200).json(doc)
console.log(req.params)
}
})
I'm new to node.js and mongoose, and I'd appreciate it if someone could help me with the below error.
I make a put request via the following function (the point of the function is to "upvote" a forum post.
o.upvote = function(post) {
return $http.put('/posts/' + post._id + '/upvote')
.success(function(data){
post.upvotes += 1;
});
};
That in turn goes to my route:
index.js (my route)
router.put('/posts/:post/upvote', function(req, res, next) {
req.post.upvote(function(err, post){
if (err) { return next(err); }
res.json(post);
});
});
And below is my model
Posts.js
var mongoose = require('mongoose');
var PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: {type: Number, default: 0},
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});
mongoose.model('Post', PostSchema);
PostSchema.methods.upvote = function(cb) {
this.upvotes += 1;
this.save(cb);
};
In my index.js route, the below error is thrown on the line "req.post.upvote":
TypeError: req.post.upvote is not a function
req.post will not be set automatically. You need another middleware to set it, but most likely you want to get it from the DB with the parameter.
const Post = mongoose.model("Post");
router.put("/posts/:post/upvote", (req, res, next) => {
Post.findById(req.params.post, (err, post) => {
if (err) return next(err);
post.upvote((err, post) => {
if (err) return next(err);
res.json(post);
});
});
});
EDIT: You also need to set the methods before you create the schema in mongoose:
PostSchema.methods.upvote = function(cb) {
this.upvotes += 1;
this.save(cb);
};
mongoose.model('Post', PostSchema);
I am currently attempting to create a .post function for a schema with document reference. However, I am not sure how I can retrieve the ObjectID of the document reference from another collection.
Board.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var BoardSchema = new Schema({
boardname: String,
userid: {type: Schema.ObjectId, ref: 'UserSchema'}
});
module.exports = mongoose.model('Board', BoardSchema);
User.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
username: String
});
module.exports = mongoose.model('User', UserSchema);
routes.js
router.route('/boards')
.get(function(req, res) {
Board.find(function(err, boards) {
if(err)
res.send(err);
res.json(boards);
});
})
.post(function(req, res) {
var board = new Board();
board.boardname = req.body.boardname;
User.find({username: req.body.username}, function(err, user) {
if(err)
res.send(err);
board.userid = user._id;
});
board.save(function(err) {
if(err)
res.send(err);
res.json({message: 'New Board created'});
});
});
To create the board, I include a boardname and a username in my request. Using the username, I do a User.find to find the specific user and assign it to board.userid. However, this does not seem to be working as board.userid does not appear.
Any help would be greatly appreciated!
Thank you!
EDIT
A better explanation of what is required is that I have an existing User collection. When I want to add a new document to Board, I would provide a username, from which I would search the User collection, obtain the ObjectId of the specific user and add it as userid to the Board document.
I believe you are looking for population
There are no joins in MongoDB but sometimes we still want references
to documents in other collections. This is where population comes in.
Try something like this:
//small change to Board Schema
var BoardSchema = new Schema({
boardname: String,
user: {type: Schema.ObjectId, ref: 'User'}
});
//using populate
Board.findOne({ boardName: "someBoardName" })
.populate('user') // <--
.exec(function (err, board) {
if (err) ..
console.log('The user is %s', board.user._id);
// prints "The user id is <some id>"
})
Sorry, I solved a different problem previously. You'll probably want to use the prevoius solution I provided at some point, so I'm leaving it.
Callbacks
The reason the userid is not on the board document is because User.find is asynchronous and is not assigned at the moment board.save(...) is called.
This should do the trick:
(Also, I added a couple of returns to prevent execution after res.send(...))
.post(function(req, res) {
var board = new Board();
board.boardname = req.body.boardname;
User.find({username: req.body.username}, function(err, user) {
if(err)
return res.send(err); //<-- note the return here!
board.userid = user._id;
board.save(function(err) {
if(err)
return res.send(err); //<-- note the return here!
res.json({message: 'New Board created'});
});
});
});