MissingSchemaError for MongoDB and NodeJS - node.js

I have a current running application on nodeJS and am connecting to mongoDB.
This is my router.js
var mongoose = require('mongoose')
, connection = require('../connection')
, Connection = mongoose.connection
, express = require('express')
, router = express.Router()
// router information
router.get('/', function(req, res) {
Connection.db.collection("users", function(err, collection){
collection.find({}).toArray(function(err, data){
console.log(data); // it will print your collection data
res.render('../views/pages/index.ejs',{data:data});
})
});
});
// add data
router.post('/add',function(req, res){
var myobj = {name:"batman", email:"batman.com", occupation:"IT director", username:"batman"};
Connection.db.collection("users", function(err, collection){
collection.insertOne(myobj, function(err){
});
});
});
module.exports = router
This is my connection.js
var mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/user', { useMongoClient: true },function () {
console.log('mongodb connected')
})
module.exports = mongoose
This is my app.js
var mongoose = require('mongoose')
, bodyParser = require('body-parser')
, PORT = 4000
, instantMongoCrud = require('express-mongo-crud') // require the module
, options = { //specify options
host: `localhost:${PORT}`
}
, route = require('./routes/router')
, express = require('express')
, app = express()
//USE AS MIDDLEWARE
app.use(bodyParser.json()); // add body parser
app.use(instantMongoCrud(options)); // use as middleware
// routes
app.use('/', route)
app.listen(PORT, ()=>{
console.log('started');
})
My router.get works fine and I am able to display the data in my index.ejs. However, for my add function it keeps throwing a
MissingSchemaError: Schema hasn't been registered for model "add".
Use mongoose.model(name, schema)
I Dont understand why this doesnt work as my schema has already been declared and I am able to query out the data. Inserting doesnt work however which I am unsure why.
Any help available?

Related

Both POST/GET requests yield a 404 error in Postman. Is my Express routing to blame?

I am intending to set up a Node.js server with MongoDB to handle HTTP CRUD requests. Upon setting up my endpoint I was initially able to receive POST/GET requests, however the handling of the document objects became the issue. Upon trying to fix this issue I am now unable to POST/GET at all? Is this simply a syntax issue or is my code doomed?
const MongoClient = require('mongodb').MongoClient;
var QRCode = require('qrcode');
var canvasu = require('canvas');
var express = require('express');
var mongoose = require('mongoose')
var app = express();
var port = process.env.PORT || 3000;
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var db;
var collection
var Patient = require('./ShiftAssist/models/patientModel');
var router = express.Router();
''
CODE FOR CONNECTION
''
router.get('/patients/:Pnum', function(req,res,next){
Patient.findOne({Pnum:req.params.Pnum},function(err,patient){
if (err) return next(err);
res.json(patient);
})
});
app.use('/', router);
app.listen(3000, function () {
console.log('Example app listening on port ' + port + '!');
});
Expected: GET request to http://127.0.0.1:3000/patients/XXXXXX with a document identifier, returns entire document
Actual: Timeout Error
try to change you route by /patients/:Pnum
and your request should be http://127.0.0.1:3000/patients/XXXXXX
source: https://expressjs.com/en/guide/routing.html
EDIT: Code i used so far
var express = require('express');
var app = express();
var router = express.Router();
router.get('/patients/:Pnum', function (req, res, next) {
setTimeout(() => res.json({ ok: req.params.Pnum }), 1000)
});
app.use('/', router);
app.listen(3000);

Node, Express, and Mongoose: Authentication failed error

I'm new to Node/Express/Mongo/MLab and backend programming in general. I am trying to submit a post request to an MLab database and running into trouble. I think my problem is with Mongoose and MLab.
Here is my Glitch project
I'm getting error MongoDB connection error: { MongoError: Authentication failed. Why am I getting this error? Is there a problem with my mongoose.connect function and credentials? Is MLab not properly set up?
'use strict';
var express = require('express');
var mongo = require('mongodb');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var validUrl = require('valid-url');
var dns = require("dns");
var cors = require('cors');
var app = express();
// Basic Configuration
var port = process.env.PORT || 3000;
// Hooks up app to MLab MongoDB database by using the .env variable I created
// Doesn't work. Data is not submitted to MLab and /api/shorturl/new endpoint freezes up when form is submitted
mongoose.connect(process.env.MONGODB_URI, {useMongoClient: true});
/*
Also doesn't work
mongoose.connect(process.env.MONGODB_URI, {
"auth":{"authSource": "admin"},
"user": "admin",
"pass": "password"
});
*/
// Should allow us to use promises with mongoose
mongoose.Promise = global.Promise;
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'MongoDB connection error:'));
// Sets up a Schema for the DB
var urlSchema = new mongoose.Schema({
url: String,
shortenedUrl: String
});
// Sets up a model for the DB
var Url = mongoose.model("Url", urlSchema);
app.use(cors());
/** this project needs to parse POST bodies **/
// you should mount the body-parser here
var urlencodedParser = bodyParser.urlencoded({ extended: false });
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.use('/public', express.static(process.cwd() + '/public'));
// parse application/x-www-form-urlencoded
app.get('/', function(req, res){
res.sendFile(process.cwd() + '/views/index.html');
});
app.get("/api/shorturl/new", function (req, res) {
res.sendFile(process.cwd() + '/views/form.html');
//res.send({hi: "hi"});
});
app.post("/api/shorturl/new", urlencodedParser, function (req,res) {
// Gets URL from form
//var url = req.body.url;
//console.log(url);
var myData = new Url(req.body);
console.log("myData : " + myData);
myData.save()
.then(item => {
res.send("Successfully saved to DB");
})
.catch(err => {
res.status(400).send("Unable to save to DB");
});
});
app.listen(port, function () {
console.log('Node.js listening ...');
});
As other people have commented the code itself looks like it should work.
so the immediate suspect is the URI,
obviously you are not going to post the full string for all of us to see, but one theory that comes to mind is your password having characters that need encoding,
try using javascripts encodeURIComponent on the password.

How to use req.params in express 4 with Mongoose

I'm stuck in using req.params.id to execute a query with Mongoose.
I use Angular but the problem don't come from here.
I just put the code that concern my server and my route files
routes.js
var Product = require('./models/product'); // My Mongoose model
var express = require('express');
var router = express.Router(); // Do I really need that ?
// function to retrieve ALL employees (working)
function getEmployees(res){
Employee.find(function(err, employees) {
if (err)
return res.send(err)
res.json(employees);
});
};
// function to retrieve ONE employee (not working)
function getEmployeeByID(req,res){
var query = Employee.where({ _id: req.params.id });
query.findOne(function (err, employee) {
if (err)
return res.send(err)
res.json(employee);
});
};
module.exports = function(app) {
// !!!!!!!!!!! PROBLEM IS HERE !!!!!!!!!!!!!!!
app.get('/employees/:employee_id', function(req, res) {
getEmployeeByID(res);
});
// ALL IS WORKING HERE
app.get('/employees', function(req, res) {
getEmployees(res);
});
app.post('/employees', function(req, res) {
Employee.create({
firstname : req.body.firstname,
lastname : req.body.lastname,
age : req.body.age,
dept : req.body.dept,
done : false
}, function(err) {
if (err)
res.send(err);
getEmployees(res);
});
});
app.delete('/employees/:employee_id', function(req, res) {
Employee.remove({
_id : req.params.employee_id
}, function(err) {
if (err)
res.send(err);
getEmployees(res);
});
});
app.use('/', router);
module.exports = router;
}; // end module.exports
Then I have my server file
// modules =================================================
var express = require('express');
var app = express();
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var db = require('./config/db');
mongoose.connect(db.url);
var port = process.env.PORT || 8080; // set our port
var router = express.Router();
// application -------------------------------------------------------------
router.get('/', function(req, res) {
res.sendfile('./public/index.html');
});
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' }));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(methodOverride('X-HTTP-Method-Override'));
app.use(express.static(__dirname + '/public'));
// routes ==================================================
require('./app/routes')(app); // pass our application into our routes
app.listen(port);
module.exports = app;
The problem is that when I land on the employees page, I have an error :
GET http://localhost:8080/employees/undefined 500 (Internal Server Error)
It's normal since I've not clicked yet an employee so no ID.
BUT, still, even with a click on one employee, it's ID is not retrieved. I mean, the URL is changed with /employees/employee_id but it won't find the ID in the function getEmployeeByID. In Terminal all the console.log give UNDEFINED even after clicking on ONE employee.
I tried many examples and rode the Docs on Express 4 but can't find what's wrong.
Thanks you if you can help.
You have an error in the way you call the getEmployeeByID function.
The function signature expects req then res, but you are sending only res to it, which will be wrongly treated as req inside the function.
Also, you should refer to the param with the name you gave it, meaning req.params.employee_id.
Now you should actually use the router instead of app which is the more classic way of doing it in Express4.
function getEmployeeByID(req, res){
var query = Employee.where({ _id: req.params.employee_id }); // <-- Use the correct param name
query.findOne(function (err, employee) {
if (err)
return res.send(err)
res.json(employee);
});
};
module.exports = function(app) {
// User router instead of app
router.get('/employees/:employee_id', function(req, res) {
getEmployeeByID(req, res); // <-- sending both req and res to the function
});
I've never used moongoose (am a mongodb native driver user) so can't comment on that part of the code.

TypeError: Cannot call method 'get' of undefined

I try to make a simple CRUD application on node.js using express.js. I try to connect to DB, but I have an error TypeError: Cannot call method 'get' of undefined. Part of my code:
app.js
var mongo = require('mongodb');
var monk = require('monk');
var db = monk('localhost:27017/notepad');
var app = express();
app.get('/users', routes.userlist);
// mongoDB
app.use(function (req, res, next) {
req.db = db; // this is setting up db property to request
next();
});
routes/index.js
exports.userlist = function (req, res) {
var db = req.db;
var collection = db.get('usercollection'); // error in this line
collection.find({}, {}, function (e, docs) {
res.render('userList', {
"userlist": docs
});
});
};
I think the instanse of DB is not setted or it's not available in other file. How to solve this?
Your app.use should be written before your app.get. The app.get is called first by Express.
var mongo = require('mongodb');
var monk = require('monk');
var db = monk('localhost:27017/notepad');
var app = express();
// mongoDB
// Do all your "pre-route" use() functions first
app.use(function (req, res, next) {
req.locals.db = db; // this is setting up db property to request
next();
});
app.get('/users', routes.userlist);
In your routes...
var db = req.locals.db; // Instead of req.db
Or even better...
var mongo = require('mongodb');
var monk = require('monk');
var db = monk('localhost:27017/notepad');
var app = express();
app.locals.db = db;
app.get('/users', routes.userlist); // Access it using req.locals.db

Access app.js variables in routes but without global express

This is my config in app.js:
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, Server = mongo.Server
, Db = mongo.Db;
, mongo = require('mongodb');
, BSON = mongo.BSONPure;
var app = express();
var server = new Server('localhost', 27017, {auto_reconnect: true, });
var db = new Db('tasksdb', server); //i need to remove this "var" to access db in routes
db.open(function(err, db) {
if(!err) {
console.log("Connected to 'tasksdb' database");
db.collection('tasks', {safe:true}, function(err, collection) {
if (err) {
console.log("The 'tasks' collection doesn't exist. Creating it with sample data...");
populateDB();
}
});
}
});
app.get('/', routes.index);
app.get('/tasks', routes.getAllTasks);
In routes/index.js i have:
exports.index = function(req, res){
res.render('index', { title: 'Express' });
};
exports.getAllTasks = function (req, res) {
db.collection( 'tasks', function ( err, collection ){ //this "db" is not accessible unless i remove "var" from db in app.js
collection.find().toArray( function ( err, items ) {
res.send(items);
})
})
};
it is of course not working unless i remove "var" from "db" in app.js, then it became global and i can access it in routes, but i don't want globals in my code and don't want to move controllers actions to app.js file. How to fix it ???
I'm not sure I understand. Isn't db global with or without var ( it looks like a global scope for me )? Besides, why don't you want it to be global? That's a good example of using globals.
But it won't get shared between files. You have to add it to exports. Try this:
app.js
exports.db = db;
routes/index.js
var db = require("app").db;
The other way is to add db to every handler like this:
app.js
app.use(function(req,res,next){
req.db = db;
next();
});
app.get('/', routes.index);
app.get('/tasks', routes.getAllTasks);
Then it should be available in any route as req.db.

Resources