Node.js Mongoose model not saving without error - node.js

Making this simple Node.js Express API I encountered an odd problem:
I am creating a model and inserting data into it and then saving it to my MongoDB. But the record is never saved but I also don't get any error. I have checked if MongoDB is running and both syslog for Node errors and mongod.log for MongoDB errors as well as my own Wilson debug.log file. All contain no errors.
I use postman to test the API and do get a response every time. It's just that the data does not get saved to MongoDB (I used the mongo console with db.collection.find() to check for inserted records).
Any idea why this could be happening?
my code:
api.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var http = require('http');
var https = require('https');
var fs = require('fs');
var winston = require('winston');
// Configure logging using Winston
winston.add(winston.transports.File, { filename: '/home/app/api/debug.log' });
winston.level = 'debug';
// Request body parser
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Enable https
var privateKey = fs.readFileSync('path to private key');
var certificate = fs.readFileSync('path to cert file');
var credentials = {
key: privateKey,
cert: certificate
};
// ROUTERS
var router = express.Router();
var speciesRouter = require('./app/routes/speciesRouter');
router.use('/species', speciesRouter);
// Routes prefix
app.use('/api/v1', router);
// SERVER STARTUP
http.createServer(app).listen(3000);
https.createServer(credentials, app).listen(3001);
speciesRouter.js
var express = require('express');
var mongoose = require('mongoose');
var router = express.Router();
var Sighting = require('../models/sighting');
var winston = require('winston');
// Database connection
var dbName = 'dbname';
mongoose.connect('mongodb://localhost:27017/' + dbName);
var db = mongoose.connection;
db.on('error', function(err){
winston.log('debug', err);
});
router.route('/')
.post(function(req, res) {
var sighting = new Sighting();
sighting.user_key = req.body.user_key;
sighting.expertise = req.body.expertise;
sighting.phone_location = req.body.phone_location;
sighting.record_time = req.body.record_time;
sighting.audio_file_location = '/var/data/tjirp1244123.wav';
sighting.probable_species = [{species_name:'Bosaap', percentage:100}];
var error = '';
winston.log('debug', 'test');
// This does not get execute I suspect..
sighting.save(function(err) {
winston.log('debug', 'save');
if (err) {
winston.log('debug', err);
error = err;
}
});
res.json({
probable_species: probable_species,
expertise: req.body.expertise,
error: error
});
});
module.exports = router;
sighting.js (model)
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var SightingSchema = new Schema({
user_key: String,
expertise: Number,
phone_location: { lat: Number, lng: Number },
record_time: Number,
audio_file_location: String,
probable_species: [{ species_name: String, percentage: Number }]
});
module.exports = mongoose.model('Sighting', SightingSchema);

Did you try updating your mongodb.
sudo npm update

You can try using promise.
return sighting.save().then(function(data){
console.log(data); // check if this executes
return res.json({
probable_species: probable_species,
expertise: req.body.expertise,
error: error
});
}).catch(function(err){
console.log(err);
});
One more thing dont use res.json outside the save function because in async code it will run without waiting for save function to complete its execution

Related

Error: Route.post() requires a callback function but got a [object Undefined]

I have created a service in node.js for basic crud operations. However when I start service it throws Route.get() requires a callback function but got a [object Undefined] error. I am not able to figure out where the error is.
Here is my code.
Models:
agreement_master.js.
const mongoose = require('mongoose');
const agreementmaster = mongoose.Schema({
ClientId:{type:Number},
UserId:{type:Number},
StartDate:{type:Date},
});
var Agreement = module.exports =
mongoose.model('Agreement',agreementmaster);
module.exports.addmAgreement=function (data,callback){
data.save(callback);
}
module.exports.getallmAgreement= function (data,callback){
var query = {status:true};
Agreement.find(query, callback);
}
routes:
agreement_master.js
var express = require('express'),
router = express.Router(),
magreement = require('../controller/agreement_master');
router.post('/addmAgreement', magreement.addmAgreement);
module.exports = router;
Controller:
agreement_master.js
const Agreement= require('../models/agreement_master');
exports.addmAgreement = function (req, res){
var data = JSON.parse(JSON.stringify(req.body));
var agreement = new Agreement(data);
agreement.ClientId = req.body.ClientId;
agreement.UserId= req.body.UserId;
agreement.StartDate=new Date();
Agreement.addmAgreement(agreement, function (err, obj) {
if (err) return res.json({err, status:'error'});
if(obj){
return res.json({
message:'agreement added',
});
}
});
};
index.js
const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const expressValidator = require('express-validator');
const cookieParser = require('cookie-parser');
mongoose.connect('mongodb://local/local-host')
const app = express();
error comes at this part in the below line:
const agreement = require('./routes/agreement_master');
app.use(morgan('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use(expressValidator());
app.use(cookieParser());
//Add Routes here
app.use('/agreement', agreement);
app.set('port', (process.env.PORT || 3001));
var server = app.listen(app.get('port'), function(){
console.log('Server Started on port ' + app.get('port'));
});
module.exports = app;
user module.exports instead of exports.
exports doest export anything and will not be used by require();
module.exports.addmAgreement = function (req, res){
var data = JSON.parse(JSON.stringify(req.body));
var agreement = new Agreement(data);
agreement.ClientId = req.body.ClientId;
agreement.UserId= req.body.UserId;
agreement.StartDate=new Date();
Agreement.addmAgreement(agreement, function (err, obj) {
if (err) return res.json({err, status:'error'});
if(obj){
return res.json({
message:'agreement added',
});
}
});
};
try this
router.post('/addmAgreement', function(req, res){
magreement.addmAgreement
});
instead of
router.post('/addmAgreement', magreement.addmAgreement);

Mongoose find query is not executing

I am trying to fetch some data from a mongodb. I am able to fetch the details from the model MyModel (defined in Server.js). But I can't execute the find method in the model Skill (defined in Skill.js).
Server.js
let express = require('express');
let app = express();
var config = require('./config/config');
let bodyParser = require('body-parser');
var mongoose = require('mongoose');
var cors = require('cors')
var path = require("path");
let Skill = require('./app/models/Skill');
const dbURI = config.dbURI;
app.use(cors());
app.use(bodyParser.json(true));
mongoose.connect(dbURI, {useNewUrlParser: true});
mongoose.connection.on('connected', function () {
console.log("Connected");
});
var MyModel = mongoose.model('Test', new Schema({ name: String
}));
Skill.findOne(function(error, result) {
console.log("1",error,result);
});
MyModel.findOne(function(error, result) {
console.log("2",error,result);
});
app.listen(config.appPort,function () {
console.log('App running on port :: "' + config.appPort.toString() + '"');
});
app/models/Skill.js
var mongoose = require('mongoose');
var skillSchema = new mongoose.Schema({
name: String,
length: String,
});
var Skill = mongoose.model('Skill', skillSchema,'Skill');
module.exports = Skill;
Output
App running on port :: "8080"
Conneccted
2 null { _id: 5c6678215c50a65e59fc6a89, name: 'test', __v: 0 }
I haven't found any issues while creating the schema. Could someone help me to resolve the issue?
I can't test my suggestion at the moment, but one thing I noticed in your code is that you queries, as in
Skill.findOne(function(error, result) {
console.log("1",error,result);
});
MyModel.findOne(function(error, result) {
console.log("2",error,result);
});
are not executed in the "connected" callback; may be it's not the main problem, but I would try to change the code as follows:
mongoose.connection.on('connected', function () {
console.log("Connected");
Skill.findOne(function(error, result) {
console.log("1",error,result);
});
MyModel.findOne(function(error, result) {
console.log("2",error,result);
});
});
The key thing is that each call (.on, .findOne) starts a promise, which encapsulates an asynchronous behaviour. I you place ,findOne invocation just after .on invocation, you can't be sure Mongoose's connection is ready when you starts .findOne...

Mongo models not responding

I'm working on a new app and trying to get mongo set up locally for storage. My api endpoints are getting hit but as soon as I try to actually call a db operation - find or save - it doesn't respond.
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var Person = require('./data/person');
var dbConfig = require('./config');
//database: 'mongodb://localhost:27017/persondb'
var db = mongoose.createConnection(dbConfig.database);
db.on('error', function() {
console.info('Error: Could not connect to MongoDB. Did you forget to run `mongod`?');
});
if (~process.argv.indexOf('mode_dev')) {
global.mode_dev = true;
console.log('Server started in dev mode.');
}
// configure app to use bodyParser()
// this will let us get the data from a POST
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/api', router);
router.route('/persons')
.post(function(req, res) {
debugger;
var person = new Person(); // create a new instance of the Person model
person.name = req.body.name;
person.save(function(err) {
debugger;
if (err)
res.send(err);
res.json({ message: 'Person created!' });
});
})
.get(function(req, res) {
Person.find(function(err, persons) {
debugger;
if (err)
res.send(err);
res.json(persons);
});
});
Here's the schema:
data/item.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var personSchema = new Schema({
name: String,
});
module.exports = mongoose.model('Person', personSchema);
I am running mongod before getting my webserver started. As soon as I get to the .save or .find calls, no error is thrown but the callbacks are never hit.
I would connect like this:
mongoose.connect("mongodb://localhost/persondb");
var db = mongoose.connection;
maybe this will help it explains problems using mongoose.createConnection(
if you use createConnection, you need to always reference that connection variable if you include a registered model, otherwise if you use mongoose to load the model, it will never actually talk to your database.
The other solution is to simply use mongoose.connect instead of
mongoose.createConnection. Then you can just use
mongoose.model(‘MyModel’) to load the requested model without needing
to carry around that db connection variable.

Can't get users using restful API with node and mongodb

When I set up the route for users in server.js and test with postman/localhost I get the error message, cannot GET /users. Same with any other crud operation. How can I fix this route?
server.js
var express = require("express");
var app = express();
var bodyParser = require("body-parser");
var router = express.Router();
var mongoOp = require("./models/mongo");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({"extended" : false}));
router.get("/",function(req,res){
res.json({"error" : false,"message" : "Hello World"});
});
router.route("/users")
.get(function(req,res){
var response = {};
mongoOp.find({},function(err,data){
// Mongo command to fetch all data from collection.
if(err) {
response = {"error" : true,"message" : "Error fetching data"};
} else {
response = {"error" : false,"message" : data};
}
res.json(response);
});
});
app.use('/',router);
app.listen(3000);
console.log("Listening to PORT 3000");
mongo.js
var mongoose = require("mongoose");
mongoose.connect('mongodb://localhost:27017/meanapi');
var mongoSchema = mongoose.Schema;
var userSchema = {
"userEmail" : String,
"userPassword" : String
};
module.exports = mongoose.model('userLogin', userSchema);
something helpful for these cases is to set NODE_ENV=development as an environment variable and use morgan. It prints out all the requests that hit your nodejs server with status code, method, path etc.
Here's a simple way to set it up:
if ('production' != app.get('env')) {
app.use(morgan('dev'));
}
Another thing that helps in debugging is
app.on('error', function (err) {
console.error(err); // or whatever logger you want to use
});
Ass that after all the middleware and it should print out if some requests fail to get all the way to your handlers.
Hope this helps!

MongoError: not authorized for query

I have a small Node.js/ Express/ Mongoose app which I have running on an AWS - EC2 instance built using Bitnami AMI, whenever I try to run .find on my app MongoDB collection using Chrome Postman I get the following result.
{
"name": "MongoError"
}
[MongoError: not authorized for query on projectDB.areas]
I tried using the following 3 connection strings but all 3 returned the same result, can someone please help by telling me what I am missing / doing wrong here? Thanks
var connectionString = 'mongodb://localhost:27017/'+dbName;
var connectionString = 'mongodb://root:bitnami#localhost:27017/'+dbName;
var connectionString = 'mongodb://root#localhost:27017/'+dbName;
My node.js app code:
area.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var areaSchema = new Schema({
name: { type: String, required: true },
});
module.exports = mongoose.model('Area', areaSchema);
areas.js
var Area = require('../app/models/area');
var express = require('express');
var router = express.Router();
router.route('/').get(function(req, res){
Area.find(function(err, areas){
if(err){
return res.send(err);
}
res.json(areas);
//res.send({sucess:true, areas:areas})
});
});
app.js
var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var areas = require('./routes/areas');
var app = express();
app.set('port', process.env.PORT || 8080);
app.use(bodyParser.json({ type: 'application/*+json' }));
var dbName = 'projectDB';
var connectionString = 'mongodb://localhost:27017/'+dbName;
// var connectionString = 'mongodb://root:bitnami#localhost:27017/'+dbName;
// var connectionString = 'mongodb://root#localhost:27017/'+dbName;
////////Tried the above 3 connection strings, none worked...
mongoose.connect(connectionString, function(err){
if(err){
throw err;
}
});
var corsOptions = {
origin: '*',
allowedHeaders: ['Content-Type'],
methods: ['POST','GET','PUT','DELETE'],
credentials: true
};
app.use(cors(corsOptions));
app.use('/api/areas', areas);
module.exports = app;
www.js
var app = require('../app');
var server = app.listen(app.get('port'), function(){
console.log('Server running on port: '+ server.address().port);
});
Since, running $ mongo admin --username root --password bitnami didn't take you into a Mongo shell.
Assuming that you ran that code on the server and not your local machine, this only means your MongoDB has not been properly setup. You should probably remove the instance completely from AWS and start setting up from scratch. Otherwise, simply follow the instructions on MongoDB website to install MongoDB.
Also, for Node.js use the following code to ensure that you have actually connected:
`
mongoose.connect("mongodb://root#localhost:27017/projectDB");
var db = mongoose.connection;
db.once('open', function () {
console.log('MongoDB connection successful.');
});
`

Resources