Related
Problem is that in my second post request I cannot get req.body. Neither console.log nor req.body show something.
In the first post request, everything seems to work just fine. And it was also working before I start to re-arrange code. I even change the type of the reply to send, but receiving the old message (status ok).
I do not understand what's going on. Any help, please?
Glitch: https://uatyroni-exercise-tracker.glitch.me - live app
code: https://glitch.com/~uatyroni-exercise-tracker
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const shortid = require('shortid');
const cors = require("cors");
//Setting MongoDB
const mongoose = require("mongoose");
mongoose.connect(process.env.MONGO_URI);
app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static("public"));
app.get("/", (req, res) => {
res.sendFile(__dirname + "/views/index.html");
});
//Defining Schema & Model
let Schema = mongoose.Schema;
let userSchema = new Schema({
id: { type: String, unique: true, default: shortid.generate },
user: String,
exercise: [{
description: String,
duration: Number,
date: {}
}]
});
let userModel = mongoose.model("Users", userSchema);
let exerciseSchema = new Schema({
userId: String,
description: String,
duration: Number,
date: String
});
let exerciseModel = mongoose.model("Exercies", exerciseSchema);
//THE POST PROCESS
app.post("/api/exercise/new-user", (req, res) => {
let userName = req.body.username;
let userNew = new userModel({ user: userName });
userModel
.find()
.exec()
.then(data => {
data = data.filter(obj => obj["user"] === userName);
console.log("I am the data: " + data);
if (data.length === 0) {
userNew
.save()
.then(result => {
res.json(result);
})
.catch(err => {
console.log(err);
res.json({ error: err });
});
} else {
res.json({ Error: "User is already registered in the database" });
}
});
});
app.post("/api/exercise/add", (req, res) => {
console.log('reqbody is: ' + req.body.description)
let newDate = '';
if (req.body.date == '') {
newDate = new Date().getFullYear() + '-' + new Date().getMonth() + '-' + new Date().getDate();
}
let newExercise = {
description: req.body.description,
duration: req.body.duration,
date: newDate
}
userModel.findById(req.body.userid, (err, data) => {
if (data.length == null)
res.json({
error: "User is not registered. Please register a user first."
});
else {
res.json(data)
}
});
});
// Not found middleware
app.use((req, res, next) => {
return next({ status: 404, message: "not found" });
});
// Error Handling middleware
app.use((err, req, res, next) => {
let errCode, errMessage;
if (err.errors) {
// mongoose validation error
errCode = 400; // bad request
const keys = Object.keys(err.errors);
// report the first validation error
errMessage = err.errors[keys[0]].message;
} else {
// generic or custom error
errCode = err.status || 500;
errMessage = err.message || "Internal Server Error";
}
res
.status(errCode)
.type("txt")
.send(errMessage);
});
const listener = app.listen(process.env.PORT || 4000, () => {
console.log("Your app is listening on port " + listener.address().port);
});
I have been doing an example based on the TV showTracker and So far I couldn't get any shows into my website. I have been trying so hard to whether I have made a mistake but I still couldn't find anything. So How to I retrieve these information. I have stared this server.js and mongod in separate CMDs and gulp in another CMD I still couldn't get any of the shows. When I see the responses it will show a blank array "[]" like this. So any advice? Help would be most appreciated. (I have host the website yet, thought this would help also to my question). The error in the net debugger says api/shows/ - response = [ ]
Here is my server.jsrespone
var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');
var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var showSchema = new mongoose.Schema({
_id: Number,
name: String,
airsDayOfWeek: String,
airsTime: String,
firstAired: Date,
genre: [String],
network: String,
overview: String,
rating: Number,
ratingCount: Number,
status: String,
poster: String,
subscribers: [{
type: mongoose.Schema.Types.ObjectId, ref: 'User'
}],
episodes: [{
season: Number,
episodeNumber: Number,
episodeName: String,
firstAired: Date,
overview: String
}]
});
var userSchema = new mongoose.Schema(
{
email: { type: String, unique: true },
password: String
});
userSchema.pre('save', function (next) {
var user = this;
if (!user.isModified('password')) return next();
bcrypt.genSalt(10, function (err, salt) {
if (err) return next(err);
bcrypt.hash(user.password, salt, function (err, hash) {
if (err) return next(err);
user.password = hash;
next();
});
});
});
userSchema.methods.comparePassword = function (candidatePassword, cb) {
bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
if (err) return cb(err);
cb(null, isMatch);
});
}
var User = mongoose.model('User', userSchema);
var Show = mongoose.model('Show', showSchema);
mongoose.connect('localhost');
var app = express();
app.set('port', process.env.PORT || 3000);
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({ secret: 'keyboard cat' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, 'public')));
app.listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
app.get('/api/shows', function (req, res, next) {
var query = Show.find();
if (req.query.genre) {
query.where({ genre: req.query.genre });
} else if (req.query.alphabet) {
query.where({ name: new RegExp('^' + '[' + req.query.alphabet + ']', 'i') });
} else {
query.limit(12);
}
query.exec(function (err, shows) {
if (err) return next(err);
res.send(shows);
});
});
app.get('/api/shows/:id', function (req, res, next) {
Show.findById(req.params.id, function (err, show) {
if (err) return next(err);
res.send(show);
});
});
app.post('/api/shows', function (req, res, next) {
var apiKey = 'E36B52F7E036AFF3';
var seriesName = req.body.showName
.toLowerCase()
.replace(/ /g, '_')
.replace(/[^\w-]+/g, '');
var parser = xml2js.Parser({
explicitArray: false,
normalizeTags: true
});
async.waterfall([
function (callback) {
request.get('http://thetvdb.com/api/GetSeries.php?seriesname=' + seriesName, function (error, response, body) {
if (error) return next(error);
parser.parseString(body, function (err, result) {
if (!result.data.series) {
return res.send(404, { message: req.body.showName + ' was not found.' });
}
var seriesId = result.data.series.seriesid || result.data.series[0].seriesid;
callback(err, seriesId);
});
});
},
function (seriesId, callback) {
request.get('http://thetvdb.com/api' + apiKey + '/series/' + seriesId + '/all/en.xml', function (error, response, body) {
if (error) return next(error);
parser.parseString(body, function (err, result) {
var series = result.data.series;
var episodes = result.data.episode;
var show = new Show({
_id: series.id,
name: series.seriesname,
airsDayOfWeek: series.airs_dayofweek,
airsTime: series.airs_time,
firstAired: series.firstaired,
genre: series.genre.split('|').filter(Boolean),
network: series.network,
overview: series.overview,
rating: series.rating,
ratingCount: series.ratingcount,
runtime: series.runtime,
status: series.status,
poster: series.poster,
episodes: []
});
_.each(episodes, function (episode) {
show.episodes.push({
season: episode.seasonnumber,
episodeNumber: episode.episodenumber,
episodeName: episode.episodename,
firstAired: episode.firstaired,
overview: episode.overview
});
});
callback(err, show);
});
});
},
function (show, callback) {
var url = 'http://thetvdb.com/banners/' + show.poster;
request({ url: url, encoding: null }, function (error, response, body) {
show.poster = 'data:' + response.headers['content-type'] + ';base64,' + body.toString('base64');
callback(error, show);
});
}
], function (err, show) {
if (err) return next(err);
show.save(function (err) {
if (err) {
if (err.code == 11000) {
return res.send(409, { message: show.name + ' already exists.' });
}
return next(err);
}
res.send(200);
});
});
});
function ensureAuthenticated(req, res, next) {
if (req.isAuthenticated()) next();
else res.send(401);
};
app.use(function (req, res, next) {
if (req.user) {
res.cookie('user', JSON.stringify(req.user));
}
next();
});
app.get('*', function (req, res) {
res.redirect('/#' + req.originalUrl);
})
app.use(function (err, req, res, next) {
console.error(err.stack);
res.send(500, { message: err.message });
});
Change var query = Show.find(); in /api/shows to
var query = Show.find(function(err, showdata){
// all the checking and the res.send(shows) goes here
})
Just wait for data and do all the operation(asynchronous)
OK Guys, I finally found the answer to the question. It's nothing wrong with the script (server.js). It is because I think it cannot hold the data in the database ('localhost:27017/test'). That is why maybe I'm getting a null response from the TVDB API. Once I changed my database and connect strings to (
'mongodb://nixsiow:abcd1234#ds027479.mongolab.com:27479/nixshowtrackrapp'
, It worked like a charm.
So maybe my answer may not explain this properly, or you can look for more details in stack overflow. Thanks for the help guys. I hope that this will help who try to do this tutorial and get stuck on this step.
So final Answer:
mongoose.connect('mongodb://nixsiow:abcd1234#ds027479.mongolab.com:27479/nixshowtrackrapp');
var agenda = require('agenda')({ db: { address: 'mongodb://nixsiow:abcd1234#ds027479.mongolab.com:27479/nixshowtrackrapp' } });
Also Nixsow's website may have a help, it is the most recent update that I found for this tutorial.
I am having a hard time wondering why, when i access my HTTP server http://localhost:8000/, i get a "Cannot GET /" message. I use express js for routing server side and angular at client-side.
I have read that this error is there because i haven't set a route for "/" path, but i don't want to route anything there, just want to let my angular handle "/".
FYI, my express server is in a different path than the angular app.
MY node code:
var bcrypt = require('bcryptjs');
var bodyParser = require('body-parser');
var cors = require('cors');
var express = require('express');
var jwt = require('jwt-simple');
var moment = require('moment');
var mongoose = require('mongoose');
var path = require('path');
var request = require('request');
var compress = require('compression');
var config = require('./config');
var User = mongoose.model('User', new mongoose.Schema({
instagramId: { type: String, index: true },
email: { type: String, unique: true, lowercase: true },
password: { type: String, select: false },
username: String,
fullName: String,
picture: String,
accessToken: String
}));
mongoose.connect(config.db);
var app = express();
app.set('port', process.env.PORT || 8000);
app.use(compress());
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public'), { maxAge: 2628000000 }));
/*
|--------------------------------------------------------------------------
| Login Required Middleware
|--------------------------------------------------------------------------
*/
function isAuthenticated(req, res, next) {
if (!(req.headers && req.headers.authorization)) {
return res.status(400).send({ message: 'You did not provide a JSON Web Token in the Authorization header.' });
}
var header = req.headers.authorization.split(' ');
var token = header[1];
var payload = jwt.decode(token, config.tokenSecret);
var now = moment().unix();
if (now > payload.exp) {
return res.status(401).send({ message: 'Token has expired.' });
}
User.findById(payload.sub, function(err, user) {
if (!user) {
return res.status(400).send({ message: 'User no longer exists.' });
}
req.user = user;
next();
})
}
/*
|--------------------------------------------------------------------------
| Generate JSON Web Token
|--------------------------------------------------------------------------
*/
function createToken(user) {
var payload = {
exp: moment().add(14, 'days').unix(),
iat: moment().unix(),
sub: user._id
};
return jwt.encode(payload, config.tokenSecret);
}
/*
|--------------------------------------------------------------------------
| Sign in with Email
|--------------------------------------------------------------------------
*/
app.post('/auth/login', function(req, res) {
User.findOne({ email: req.body.email }, '+password', function(err, user) {
if (!user) {
return res.status(401).send({ message: { email: 'Incorrect email' } });
}
bcrypt.compare(req.body.password, user.password, function(err, isMatch) {
if (!isMatch) {
return res.status(401).send({ message: { password: 'Incorrect password' } });
}
user = user.toObject();
delete user.password;
var token = createToken(user);
res.send({ token: token, user: user });
});
});
});
/*
|--------------------------------------------------------------------------
| Create Email and Password Account
|--------------------------------------------------------------------------
*/
app.post('/auth/signup', function(req, res) {
User.findOne({ email: req.body.email }, function(err, existingUser) {
if (existingUser) {
return res.status(409).send({ message: 'Email is already taken.' });
}
var user = new User({
email: req.body.email,
password: req.body.password
});
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(user.password, salt, function(err, hash) {
user.password = hash;
user.save(function() {
var token = createToken(user);
res.send({ token: token, user: user });
});
});
});
});
});
/*
|--------------------------------------------------------------------------
| Sign in with Instagram
|--------------------------------------------------------------------------
*/
app.post('/auth/instagram', function(req, res) {
var accessTokenUrl = 'https://api.instagram.com/oauth/access_token';
var params = {
client_id: req.body.clientId,
redirect_uri: req.body.redirectUri,
client_secret: config.clientSecret,
code: req.body.code,
grant_type: 'authorization_code'
};
// Step 1. Exchange authorization code for access token.
request.post({ url: accessTokenUrl, form: params, json: true }, function(error, response, body) {
// Step 2a. Link user accounts.
if (req.headers.authorization) {
User.findOne({ instagramId: body.user.id }, function(err, existingUser) {
var token = req.headers.authorization.split(' ')[1];
var payload = jwt.decode(token, config.tokenSecret);
User.findById(payload.sub, '+password', function(err, localUser) {
if (!localUser) {
return res.status(400).send({ message: 'User not found.' });
}
// Merge two accounts. Instagram account takes precedence. Email account is deleted.
if (existingUser) {
existingUser.email = localUser.email;
existingUser.password = localUser.password;
localUser.remove();
existingUser.save(function() {
var token = createToken(existingUser);
return res.send({ token: token, user: existingUser });
});
} else {
// Link current email account with the Instagram profile information.
localUser.instagramId = body.user.id;
localUser.username = body.user.username;
localUser.fullName = body.user.full_name;
localUser.picture = body.user.profile_picture;
localUser.accessToken = body.access_token;
localUser.save(function() {
var token = createToken(localUser);
res.send({ token: token, user: localUser });
});
}
});
});
} else {
// Step 2b. Create a new user account or return an existing one.
User.findOne({ instagramId: body.user.id }, function(err, existingUser) {
if (existingUser) {
var token = createToken(existingUser);
return res.send({ token: token, user: existingUser });
}
var user = new User({
instagramId: body.user.id,
username: body.user.username,
fullName: body.user.full_name,
picture: body.user.profile_picture,
accessToken: body.access_token
});
user.save(function() {
var token = createToken(user);
res.send({ token: token, user: user });
});
});
}
});
});
app.get('/api/feed', isAuthenticated, function(req, res) {
var feedUrl = 'https://api.instagram.com/v1/users/self/feed';
var params = { access_token: req.user.accessToken };
request.get({ url: feedUrl, qs: params, json: true }, function(error, response, body) {
if (!error && response.statusCode == 200) {
res.send(body.data);
}
});
});
app.get('/api/media/:id', isAuthenticated, function(req, res) {
var mediaUrl = 'https://api.instagram.com/v1/media/' + req.params.id;
var params = { access_token: req.user.accessToken };
request.get({ url: mediaUrl, qs: params, json: true }, function(error, response, body) {
if (!error && response.statusCode == 200) {
res.send(body.data);
}
});
});
app.post('/api/like', isAuthenticated, function(req, res) {
var mediaId = req.body.mediaId;
var accessToken = { access_token: req.user.accessToken };
var likeUrl = 'https://api.instagram.com/v1/media/' + mediaId + '/likes';
request.post({ url: likeUrl, form: accessToken, json: true }, function(error, response, body) {
if (response.statusCode !== 200) {
return res.status(response.statusCode).send({
code: response.statusCode,
message: body.meta.error_message
});
}
res.status(200).end();
});
});
app.listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
In that case, then you should catch all the routes in / to angular.
Put this code at the very last of your route definitions before error handlers.
app.get('*', function (req, res) {
res.sendFile('/path/to/angular/index.html');
});
As you are using Angular for your web app, you would want your express server to serve all the files related to the front-end so when you land on the link "http://localhost:8000/", Express would serve the related files back. This folder would include .js, .css and .html files as well as all the other resources (images, videos etc.) so you can link them in your markup. (eg link href="/logo.png").
You can serve these files using Express by telling express to use the Static Middleware.
Using the Middleware, you would tell Express to serve the contents of a specific folder as static resources. Putting your Angular App in the folder would then let Angular handle the routes.
var publicFolder = path.join(__dirname, '../client')
app.use(express.static(publicFolder);
You would register other endpoints to create an API for your web app. So express server would be able to provide data to the Angular app through those endpoints.
I know how to...
Remove a single document.
Remove the collection itself.
Remove all documents from the collection with Mongo.
But I don't know how to remove all documents from the collection with Mongoose. I want to do this when the user clicks a button. I assume that I need to send an AJAX request to some endpoint and have the endpoint do the removal, but I don't know how to handle the removal at the endpoint.
In my example, I have a Datetime collection, and I want to remove all of the documents when the user clicks a button.
api/datetime/index.js
'use strict';
var express = require('express');
var controller = require('./datetime.controller');
var router = express.Router();
router.get('/', controller.index);
router.get('/:id', controller.show);
router.post('/', controller.create);
router.put('/:id', controller.update);
router.patch('/:id', controller.update);
router.delete('/:id', controller.destroy);
module.exports = router;
api/datetime/datetime.controller.js
'use strict';
var _ = require('lodash');
var Datetime = require('./datetime.model');
// Get list of datetimes
exports.index = function(req, res) {
Datetime.find(function (err, datetimes) {
if(err) { return handleError(res, err); }
return res.json(200, datetimes);
});
};
// Get a single datetime
exports.show = function(req, res) {
Datetime.findById(req.params.id, function (err, datetime) {
if(err) { return handleError(res, err); }
if(!datetime) { return res.send(404); }
return res.json(datetime);
});
};
// Creates a new datetime in the DB.
exports.create = function(req, res) {
Datetime.create(req.body, function(err, datetime) {
if(err) { return handleError(res, err); }
return res.json(201, datetime);
});
};
// Updates an existing datetime in the DB.
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Datetime.findById(req.params.id, function (err, datetime) {
if (err) { return handleError(res, err); }
if(!datetime) { return res.send(404); }
var updated = _.merge(datetime, req.body);
updated.save(function (err) {
if (err) { return handleError(res, err); }
return res.json(200, datetime);
});
});
};
// Deletes a datetime from the DB.
exports.destroy = function(req, res) {
Datetime.findById(req.params.id, function (err, datetime) {
if(err) { return handleError(res, err); }
if(!datetime) { return res.send(404); }
datetime.remove(function(err) {
if(err) { return handleError(res, err); }
return res.send(204);
});
});
};
function handleError(res, err) {
return res.send(500, err);
}
DateTime.remove({}, callback) The empty object will match all of them.
.remove() is deprecated. instead we can use deleteMany
DateTime.deleteMany({}, callback).
In MongoDB, the db.collection.remove() method removes documents from a collection. You can remove all documents from a collection, remove all documents that match a condition, or limit the operation to remove just a single document.
Source: Mongodb.
If you are using mongo sheel, just do:
db.Datetime.remove({})
In your case, you need:
You didn't show me the delete button, so this button is just an example:
<a class="button__delete"></a>
Change the controller to:
exports.destroy = function(req, res, next) {
Datetime.remove({}, function(err) {
if (err) {
console.log(err)
} else {
res.end('success');
}
}
);
};
Insert this ajax delete method in your client js file:
$(document).ready(function(){
$('.button__delete').click(function() {
var dataId = $(this).attr('data-id');
if (confirm("are u sure?")) {
$.ajax({
type: 'DELETE',
url: '/',
success: function(response) {
if (response == 'error') {
console.log('Err!');
}
else {
alert('Success');
location.reload();
}
}
});
} else {
alert('Canceled!');
}
});
});
MongoDB shell version v4.2.6
Node v14.2.0
Assuming you have a Tour Model: tourModel.js
const mongoose = require('mongoose');
const tourSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'A tour must have a name'],
unique: true,
trim: true,
},
createdAt: {
type: Date,
default: Date.now(),
},
});
const Tour = mongoose.model('Tour', tourSchema);
module.exports = Tour;
Now you want to delete all tours at once from your MongoDB, I also providing connection code to connect with the remote cluster.
I used deleteMany(), if you do not pass any args to deleteMany(), then it will delete all the documents in Tour collection.
const mongoose = require('mongoose');
const Tour = require('./../../models/tourModel');
const conStr = 'mongodb+srv://lord:<PASSWORD>#cluster0-eeev8.mongodb.net/tour-guide?retryWrites=true&w=majority';
const DB = conStr.replace('<PASSWORD>','ADUSsaZEKESKZX');
mongoose.connect(DB, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
useUnifiedTopology: true,
})
.then((con) => {
console.log(`DB connection successful ${con.path}`);
});
const deleteAllData = async () => {
try {
await Tour.deleteMany();
console.log('All Data successfully deleted');
} catch (err) {
console.log(err);
}
};
Your_Mongoose_Model.deleteMany({}) can do the job
References:
https://mongoosejs.com/docs/api.html#query_Query-deleteMany
https://www.geeksforgeeks.org/mongoose-deletemany-function/
I'm building a node.js app that is a REST api using express and mongoose for my mongodb. I've got the CRUD endpoints all setup now, but I was just wondering two things.
How do I expand on this way of routes, specifically, how do I share modules between routes. I want each of my routes to go in a new file, but obviously only one database connection as you can see i've included mongoose at the top of people.js.
Do I have to write out the schema of the model 3 times in my people.js? The first schema defines the model, then I list all the vars out in the createPerson and updatePerson functions. This feels like how I made php/mysql CRUD back in the day lol. For the update function, I've tried writing a loop to loop through "p" to auto detect what fields to update, but to no avail. Any tips or suggestions would be great.
Also, I'd love any opinions on the app as a whole, being new to node, it's hard to know that the way you are doing something is the most efficient or "best" practice. Thanks!
app.js
// Node Modules
var express = require('express');
app = express();
app.port = 3000;
// Routes
var people = require('./routes/people');
/*
var locations = require('./routes/locations');
var menus = require('./routes/menus');
var products = require('./routes/products');
*/
// Node Configure
app.configure(function(){
app.use(express.bodyParser());
app.use(app.router);
});
// Start the server on port 3000
app.listen(app.port);
/*********
ENDPOINTS
*********/
// People
app.get('/people', people.allPeople); // Return all people
app.post('/people', people.createPerson); // Create A Person
app.get('/people/:id', people.personById); // Return person by id
app.put('/people/:id', people.updatePerson); // Update a person by id
app.delete('/people/:id', people.deletePerson); // Delete a person by id
console.log('Server started on port ' + app.port);
people.js
//Database
var mongoose = require("mongoose");
mongoose.connect('mongodb://Shans-MacBook-Pro.local/lantern/');
// Schema
var Schema = mongoose.Schema;
var Person = new Schema({
first_name: String,
last_name: String,
address: {
unit: Number,
address: String,
zipcode: String,
city: String,
region: String,
country: String
},
image: String,
job_title: String,
created_at: { type: Date, default: Date.now },
active_until: { type: Date, default: null },
hourly_wage: Number,
store_id: Number, // Inheirit store info
employee_number: Number
});
var PersonModel = mongoose.model('Person', Person);
// Return all people
exports.allPeople = function(req, res){
return PersonModel.find(function (err, person) {
if (!err) {
return res.send(person);
} else {
return res.send(err);
}
});
}
// Create A Person
exports.createPerson = function(req, res){
var person = new PersonModel({
first_name: req.body.first_name,
last_name: req.body.last_name,
address: {
unit: req.body.address.unit,
address: req.body.address.address,
zipcode: req.body.address.zipcode,
city: req.body.address.city,
region: req.body.address.region,
country: req.body.address.country
},
image: req.body.image,
job_title: req.body.job_title,
hourly_wage: req.body.hourly_wage,
store_id: req.body.location,
employee_number: req.body.employee_number
});
person.save(function (err) {
if (!err) {
return res.send(person);
} else {
console.log(err);
return res.send(404, { error: "Person was not created." });
}
});
return res.send(person);
}
// Return person by id
exports.personById = function (req, res){
return PersonModel.findById(req.params.id, function (err, person) {
if (!err) {
return res.send(person);
} else {
console.log(err);
return res.send(404, { error: "That person doesn't exist." });
}
});
}
// Delete a person by id
exports.deletePerson = function (req, res){
return PersonModel.findById(req.params.id, function (err, person) {
return person.remove(function (err) {
if (!err) {
return res.send(person.id + " deleted");
} else {
console.log(err);
return res.send(404, { error: "Person was not deleted." });
}
});
});
}
// Update a person by id
exports.updatePerson = function(req, res){
return PersonModel.findById(req.params.id, function(err, p){
if(!p){
return res.send(err)
} else {
p.first_name = req.body.first_name;
p.last_name = req.body.last_name;
p.address.unit = req.body.address.unit;
p.address.address = req.body.address.address;
p.address.zipcode = req.body.address.zipcode;
p.address.city = req.body.address.city;
p.address.region = req.body.address.region;
p.address.country = req.body.address.country;
p.image = req.body.image;
p.job_title = req.body.job_title;
p.hourly_wage = req.body.hourly_wage;
p.store_id = req.body.location;
p.employee_number = req.body.employee_number;
p.save(function(err){
if(!err){
return res.send(p);
} else {
console.log(err);
return res.send(404, { error: "Person was not updated." });
}
});
}
});
}
I have taken another approach here. Not saying it is the best, but let me explain.
Each schema (and model) is in its own file (module)
Each group of routes for a particular REST resource are in their own file (module)
Each route module just requires the Mongoose model it needs (only 1)
The main file (application entry point) just requires all route modules to register them.
The Mongo connection is in the root file and is passed as parameter to whatever needs it.
I have two subfolders under my app root - routes and schemas.
The benefits of this approach are:
You only write the schema once.
You do not pollute your main app file with route registrations for 4-5 routes per REST resource (CRUD)
You only define the DB connection once
Here is how a particular schema file looks:
File: /schemas/theaterSchema.js
module.exports = function(db) {
return db.model('Theater', TheaterSchema());
}
function TheaterSchema () {
var Schema = require('mongoose').Schema;
return new Schema({
title: { type: String, required: true },
description: { type: String, required: true },
address: { type: String, required: true },
latitude: { type: Number, required: false },
longitude: { type: Number, required: false },
phone: { type: String, required: false }
});
}
Here is how a collection of routes for a particular resource looks:
File: /routes/theaters.js
module.exports = function (app, options) {
var mongoose = options.mongoose;
var Schema = options.mongoose.Schema;
var db = options.db;
var TheaterModel = require('../schemas/theaterSchema')(db);
app.get('/api/theaters', function (req, res) {
var qSkip = req.query.skip;
var qTake = req.query.take;
var qSort = req.query.sort;
var qFilter = req.query.filter;
return TheaterModel.find().sort(qSort).skip(qSkip).limit(qTake)
.exec(function (err, theaters) {
// more code
});
});
app.post('/api/theaters', function (req, res) {
var theater;
theater.save(function (err) {
// more code
});
return res.send(theater);
});
app.get('/api/theaters/:id', function (req, res) {
return TheaterModel.findById(req.params.id, function (err, theater) {
// more code
});
});
app.put('/api/theaters/:id', function (req, res) {
return TheaterModel.findById(req.params.id, function (err, theater) {
// more code
});
});
app.delete('/api/theaters/:id', function (req, res) {
return TheaterModel.findById(req.params.id, function (err, theater) {
return theater.remove(function (err) {
// more code
});
});
});
};
And here is the root application file, which initialized the connection and registers all routes:
File: app.js
var application_root = __dirname,
express = require('express'),
path = require('path'),
mongoose = require('mongoose'),
http = require('http');
var app = express();
var dbProduction = mongoose.createConnection('mongodb://here_insert_the_mongo_connection_string');
app.configure(function () {
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(application_root, "public")));
app.use('/images/tmb', express.static(path.join(application_root, "images/tmb")));
app.use('/images/plays', express.static(path.join(application_root, "images/plays")));
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.get('/api', function (req, res) {
res.send('API is running');
});
var theatersApi = require('./routes/theaters')(app, { 'mongoose': mongoose, 'db': dbProduction });
// more code
app.listen(4242);
Hope this was helpful.
I found this StackOverflow post very helpful:
File Structure of Mongoose & NodeJS Project
The trick is to put your schema into models directory. Then, in any route, you can require('../models').whatever.
Also, I generally start the mongoose db connection in app.js, and only start the Express server once the connection is up:
mongoose.connect('mongodb://localhost/whateverdb')
mongoose.connection.on('error', function(err) {
console.log("Error while connecting to MongoDB: " + err);
process.exit();
});
mongoose.connection.on('connected', function(err) {
console.log('mongoose is now connected');
// start app here
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
});
I'd take a look at this project https://github.com/madhums/node-express-mongoose-demo . It is a great example on how to build a nodejs application in a standard way.