TypeError from Mongoose - javascript

I made an express app, and it has an app inside of that called users. I am using Typescript. This is what my app.js file looks like:
///<reference path='d.ts/DefinitelyTyped/node/node.d.ts' />
///<reference path='d.ts/DefinitelyTyped/express/express.d.ts' />
///<reference path='routes/Users.ts' />
import express = require("express");
import http = require("http");
import path = require("path");
import us = require("./routes/Users");
var app = express();
// all environments
app.set('port', 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.set('env', 'development');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(require('less-middleware')({ src: __dirname + '/public' }));
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', (req, res) => {
res.render("index", {
title: "Express Main Page"
});
});
// Users app
app.use(us.Users.users);
http.createServer(app).listen(app.get('port'), () => {
console.log('Express server listening on port ' + app.get('port'));
});
Right now, the problem is this, I am using mongoose to store some data, and I have mongodb started. Here is what the Users.ts file looks like:
/// <reference path='../d.ts/DefinitelyTyped/node/node.d.ts' />
/// <reference path='../d.ts/DefinitelyTyped/express/express.d.ts' />
/// <reference path='../d.ts/DefinitelyTyped/mongoose/mongoose.d.ts' />
import express = require("express");
import mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/SimpleBlog");
export module Users {
// Exporting information about the user class
export var users: Express = express();
export var base_URL: string = "/users";
// Making Schemas
var UserSchema = new mongoose.Schema({
email: String,
name: String,
age: Number
});
// Attaining users
var db_Users = mongoose.model('Users', UserSchema);
var list;
db_Users.find({}, (err, docs) => {
list = docs;
console.log(docs);
});
// Route for base url
users.get(base_URL, (req, res) => {
res.render("Users/index", {
title: "User List",
user_list: list
});
});
// Route for POST request
users.post(base_URL + "/add", (req, res) => {
try {
console.log(req.body['name']);
new UserSchema({
name: req.body['name'],
email: req.body['email'],
age: req.body['age']
}).save(function (err, docs) {
if (err) { console.log(err); }
});
} catch (Exception) {
console.log(Exception);
}
res.redirect(base_URL);
});
users.get(base_URL + "/add", (req, res) => {
res.render("Users/add", {});
});
}
I get [TypeError: object is not a function] as the error, when I try to save.
The users/add simple gives the user a registration form, and this is done in a jade file. I can also attest that it is not a problem with express.bodyParser() since console.log(req.body['name']); prints out the name of the post request correctly.
Any help regarding this would be helpful.

Your syntax isn't correct for Mongoose.
Regarding this line:
// Attaining users
var db_Users = mongoose.model('Users', UserSchema);
That line returns a Model function/constructor. You'll use that result to create instances of a User. Given all of the Users/UserSchema/User namespace you've got right now, it's a little confusing, so I'll switch it:
// Attaining users
var UserModel = mongoose.model('User', UserSchema);
It looks like the class represents a User, not Users.
When you want to create an instance of a User, you'd create an instance of the UserModel class rather than the schema:
new UserModel({
name: req.body['name'],
email: req.body['email'],
age: req.body['age']
}).save(function (err, docs) {
if (err) { console.log(err); }
});

Related

db.getConnection is not a function

I am trying to make a post request to my first app, but every time I go to make the post, it gives me this error: TypeError: db.getConnection is not a function
I have tried all of stack overflows suggestions, but I still can't seem to get it to work after messing around with the code for the last 2 days. I am a beginner so please forgive me, but here is what my code looks like...
my db.js looks like this....
var mysql = require('mysql');
var mainDb = mysql.createPool({
host : process.env.mysql_host,
user : process.env.mysql_user,
password : process.env.mysql_pwd,
database : process.env.mysql_db
});
exports.getConnection = function(callback) {
mainDb.getConnection(function(err, connection) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
callback(err, connection);
});
};
and my register.js code looks like this...
var express = require('express');
var router = express.Router();
var db = require(__dirname, 'models/db');
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
router.get('/register', function(req, res, next) {
res.render('register', { title: 'Register for a free account' });
});
router.post('/register', function(req, res) {
var input = JSON.parse(JSON.stringify(req.body));
var today = new Date();
var users = {
"username": req.body.username,
"email":req.body.email,
"password":req.body.password,
"created":today,
"modified":today
};
db.getConnection(function(err, connection) {
connection.query('INSERT INTO users SET ? ', users, function(err, result) {
connection.release();
if (err) { return console.error(err); }
});
});
res.redirect('/index');
});
module.exports = router;
I don't know if my app.js is relevant for this question, but it looks like this...
const express = require('express');
http = require('http');
path = require('path');
session = require('express-session');
app = express();
mysql = require('mysql');
bodyParser = require('body-parser');
db = require(__dirname, 'models/db')
var index = require('./routes/index');
var register = require('./routes/register');
app.use('/', index);
app.use('/', register);
var engine = require('ejs-mate');
app.engine('ejs', engine);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(express.static(path.join(__dirname, 'public')));
var server = http.createServer(app);
var port = 8995;
server.listen(port);
module.exports = app;
When I start app.js I get no errors, only when I make my post request from my form, the error shows up in my browser. Please help!
At db.js you are exporting only a function. But at register.js, you are trying to use db as if it was an object.
To solve your problem, at db.js, just export an object, instead of a function:
function getConnection(callback) {
mainDb.getConnection(function(err, connection) {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
callback(err, connection);
}
module.exports = { getConnection };
You don't need use getConnection method only exports the pool, according the documentation.
https://github.com/mysqljs/mysql

Passing Mongo DB Object DB to Express Middleware

I am having problems trying to access the "DB" database object that is created when the MongoDB client module connects to my MongoDB database.
At the moment I am getting an error stating that, within data.js, 'db' is not defined. I understand why this is - the db object is not being "passed" through to the router and then subsequently through to the controller.
What is the best way to do this?
I have tried to pass the "db" object through to the router (dataRoutes.js) but I cannot figure how to make this accessible to the controller (data.js). Could someone please help?
Please note I have not included the other routes and controllers but they simply submit a Form via the POST method to /data/submit . The controller below is meant to write this form data to the MongoDB database.
Here is the relevant code:
app.js
var express = require('express');
var path = require('path')
var MongoClient = require('mongodb').MongoClient;
var bodyParser = require('body-parser');
var app = express();
var routes = require('./routes/index');
var dataRoutes = require('./routes/dataRoutes');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
MongoClient.connect("mongodb://localhost:27017/m101", function(err, db) {
if(err) throw err;
console.log("Successfully connected to MongoDB.");
app.use('/', routes); // Use normal routes for wesbite
app.use('/data', dataRoutes);
app.get('/favicon.ico', function(req, res) {
res.send(204);
});
app.use(function(req, res, next) {
var err = new Error('Oops Page/Resource Not Found!');
err.status = 404;
next(err); //Proceed to next middleware
});
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
// update the error responce, either with the error status
// or if that is falsey use error code 500
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
app.use(function(err, req, res, next) {
console.log('Error');
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
var server = app.listen(3000, function() {
var port = server.address().port;
console.log("Express server listening on port %s.", port);
});
});
dataRoutes.js
// router
var express = require('express');
var router = express.Router();
// controller references
var ctrlsData = require('../controllers/data');
router.post('/submit', ctrlsData.submit);
module.exports = router;
data.js
var MongoClient = require('mongodb').MongoClient;
var sendJsonResponse = function(res, status, content) {
res.status(status);
res.json(content);
};
module.exports.submit = function(req, res) {
var title = req.body.title;
var year = req.body.year;
var imdb = req.body.imdb;
/*
console.log('submitted');
console.log(req.body);
sendJsonResponse(res, 201, {title,year,imdb});
*/
var title = req.body.title;
var year = req.body.year;
var imdb = req.body.imdb;
if ((title == '') || (year == '') || (imdb == '')) {
sendJsonResponse(res, 404, {
"message": "Title, Year and IMDB Reference are all required."
});
} else {
db.collection('movies').insertOne(
{ 'title': title, 'year': year, 'imdb': imdb },
function (err, r) {
if (err) {
sendJsonResponse(res, 400, err);
} else {
sendJsonResponse(res, 201, "Document inserted with _id: " + r.insertedId + {title,year,imdb});
}
}
);
}
};
Create a db variable that reference mongodb in app.js :
MongoClient.connect("mongodb://localhost:27017/m101", function(err, db) {
app.db = db;
//.....
});
In data.js, access db from req.app :
module.exports.submit = function(req, res) {
req.app.db.collection('movies').insertOne({ 'title': title, 'year': year, 'imdb': imdb },
function(err, r) {}
)
};
The accepted answer isn't quite correct. You shouldn't attach custom objects to the app object. That's what app.locals is for. Plus, the accepted answer will fail when using Typescript.
app.locals.db = db;
router.get('/foo', (req) => {
req.app.locals.db.insert('bar');
});
Sure, it's longer. But you get the assurance that future updates to ExpressJS will not interfere with your object.
I understand that the answer of #Bertrand is functional, but it is not usually recommended. The reason being that, from a software point of view, you should have a better separation in your software.
app.js
var express = require('express');
var path = require('path')
var MongoClient = require('mongodb').MongoClient;
var bodyParser = require('body-parser');
var app = express();
var routes = require('./routes/index');
var dataRoutes = require('./routes/dataRoutes');
var DB = require('./db.js');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
DB.Init("mongodb://localhost:27017/m101")
.then(() => {
console.log("Successfully connected to MongoDB.");
app.use('/', routes); // Use normal routes for wesbite
app.use('/data', dataRoutes);
app.get('/favicon.ico', function(req, res) {
res.send(204);
});
var server = app.listen(3000, function() {
var port = server.address().port;
console.log("Express server listening on port %s.", port);
});
})
.catch((e) => {
console.log("Error initializing db");
});
db.js
var _db = null;
module.exports = {
Init: (url) => {
return new Promise((resolve, reject) => {
if (!url)
reject("You should provide a URL");
MongoClient.connect("mongodb://localhost:27017/m101", function(err, db) {
if(err) reject(err);
_db = db;
resolve(); // Or resolve(db) if you wanna return the db object
});
});
},
Submit: (req, res, next) => {
// Whatever goes. You have access to _db here, too!
}
};
in data.js
var DB = require('../db.js');
router.post('/submit', DB.submit);
Finally, even this answer can be improved as you are not usually advised to wait for the DB to connect, otherwise, you are losing the advantage of using ASync procs.
Consider something similar to here in app.js:
Promise.resolve()
.then(() => {
// Whatever DB stuff are
// DB.Init ?
})
.then(() => {
// Someone needs routing?
})
...
.catch((e) => {
console.error("Ther app failed to start");
console.error(e);
});
I understand that in the last sample, you can not instantly query DB as it may not have connected yet, but this is a server, and users are usually expected to wait for your DB to init. However, if you wanna more proof solution, consider implementing something yourself in DB.submit to wait for the connect. Or, you can also use something like mongoose.

Login Form in Node.js & MongoDB (mongoose)

I'm almost beginner to web dev. I'm making a pretty basic web page for login authentication. All I'm trying to do is to check user credentials (username & password) on my LoginPage from the database (mongoose) and redirect to the next page (MainPage) if they are correct.
Login.ejs (.html) file
<html>
<head>
<title>Login</title>
</head>
<body>
<form id="form_Login" action="/MainPage" method="post">
<input id="txt_username" type="text" required>
<br><input id="txt_password" type="password" required>
<br><input type="submit" value="Login">
</form>
</body>
</html>
app.js file
var express = require('express');
var app = express();
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = new Schema ({
username : String,
password : String
});
mongoose.model('User',User);
mongoose.connect('mongodb://localhost:27017/MyDB');
app.set('view engine', 'ejs');
app.get('/',function(req, res) {
res.render('LoginPage');
});
app.get('/MainPage',function(req, res) {
res.render('MainPage');
});
app.post('/MainPage', function(req, res) {
// new code should come over here
res.redirect('/MainPage');
});
app.get('*', function(req, res) {
res.send('Bad Route!');
});
var server = app.listen(3000, function() {
console.log('listening on port 3000.');
});
Any help would be appreciated.
I would suggest you use the passport.js library for that.
Not only does it provide you with a good way to create local authentication, you can later on integrate google, facebook and twitter (or any oAuth) social authentication methods.
You can read the documentation which should provide you with a good starting point, or any one of these examples:
http://passportjs.org/docs
http://mherman.org/blog/2013/11/11/user-authentication-with-passport-dot-js/#.VYAS0PlViko
http://mherman.org/blog/2015/01/31/local-authentication-with-passport-and-express-4/#.VYAS0vlViko
https://scotch.io/tutorials/easy-node-authentication-setup-and-local ( I have used this one in the past)
I suggest you start by using the passport-local scheme, which will give you exactly what you need. https://github.com/jaredhanson/passport-local
Use the body-parser middleware to get your form data and use it to query your database. First you need to do a npm install body-parser. Then you could try something like the following. Note that this is very rough code however and you should probably use some other excellent libraries to handle authentication.
var express = require('express');
var app = express();
var bodyParser = require('body-parser);
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = new Schema ({
username : String,
password : String
});
mongoose.model('User',User);
mongoose.connect('mongodb://localhost:27017/MyDB');
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs');
app.get('/',function(req,res)
{
res.render('LoginPage');
});
app.get('/MainPage',function(req,res)
{
res.render('MainPage');
});
app.post('/MainPage', function(req, res)
{
// new code should come over here
User.findOne({username: req.body.username, password: req.body.password}, function(err, user){
if(err) {
console.log(err);
}
else if(user){
res.redirect('/MainPage');
}
else {
console.log('Invalid');
}
});
});
app.get('*', function(req,res)
{
res.send('Bad Route!');
});
var server = app.listen(3000, function() {
console.log('listening on port 3000.');
});
You can use bodyPasser to get input from the html. (npm i body-parser. https://www.npmjs.com/package/body-parser).
You can use the mongoose to save the user and find the user (npm i mongoose) https://www.npmjs.com/package/mongoose.
I used here ejs.
Using the findOne you can find the register user is available or not https://mongoosejs.com/docs/api/model.html#model_Model-findOne.
//jshint esversion:6
const express = require('express');
const bodyPasser = require('body-parser');
const ejs = require('ejs');
const mongoose = require('mongoose');
const app = express();
app.use(express.static('public'));
app.set('view engine','ejs');
app.use(bodyPasser.urlencoded({ extended: true }));
mongoose.set("strictQuery", false);
mongoose.connect('mongodb://localhost:27017/userDB',{useNewUrlParser:true})
.then(() => console.log('Connected!'));
const userSchema = {
email:String,
password:String
}
const User = new mongoose.model("User",userSchema);
app.get("/",(req,res)=>{
res.render("home")
})
app.get("/register",(req,res)=>{
res.render("register")
})
app.get("/login",(req,res)=>{
res.render("login")
})
app.post("/register",(req,res)=>{
const newUser = new User({
email: req.body.username,
password: req.body.password,
});
newUser.save((err)=>{
if(err){
console.log(err);
}else{
res.render("secrets")
}
})
})
app.post("/login",(req,res)=>{
const username = req.body.username;
const password = req.body.password;
User.findOne({email:username},(err,user)=>{
if(err){
console.log(err);
}else{
if(user){
if(user.password === password){
res.render("secrets")
}
}
}
})
})
app.listen(3000,function(){
console.log("port is statrt at 3000");
})

Define mongoose and Schema only ones

Hi i am developing nodejs application with express and mongodb.So i must define mongoose and schema in my all routing js to use mongo and schema. I want to define them only ones. I am new at node.js so please be patient. My project structure:
My route.js is shown below:
var routes = function (app) {
app.locals.error=null;
app.get('/login', function (req, res) {
return res.render(__dirname + "/views/login", {
title: 'Giriş',
stylesheet: 'login'
});
});
var mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/fuatblog");
var UserSchema = new mongoose.Schema({
name: String,
email: String,
password: String,
age: Number
}),
Users = mongoose.model('Users', UserSchema);
app.post('/sessions', function (req, res) {
console.log(req.body.login.email);
console.log(req.body.login.password);
console.log(req.body.login.rememberMe);
Users.find({
email: req.body.login.email,
password: req.body.login.password
}, function (err, docs) {
if (! docs.length) {
// no results...
console.log('User Not Found');
res.status(400);
return res.render(__dirname + "/views/login", {
title: 'Giriş',
stylesheet: 'login',
error: 'Kullanıcı adı veya şifre yanlış'
});
}
console.log('User found');
req.session.email = docs[0].email;
console.log(req.session.email);
return res.redirect('/Management');
});
});
};
module.exports = routes;
And my server.js(app.js)
/**
* Module dependencies.
*/
////Mongoose eklendi
var express = require('express'),
mongoose= require('mongoose');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
////Cookie için eklendi.
app.use(express.cookieParser());
////Session desteği için eklendi
app.use(express.session({secret: 'asdfsdfsafasdfasdfasdf'}));
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
////Put ve Delete mothodları için
app.use(express.methodOverride());
////Requeestleri ayrıştırmak için kullanılıyor
app.use(express.bodyParser());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
////Helpers
//require('./apps/helpers')(app);
//Routes
require('./apps/authentication/routes')(app)
require('./apps/blog/routes')(app)
require('./apps/management/routes')(app)
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
I'm going to assume that you meant that you want to define the Schema only ONCE.
What I like to do is to initialize all the models that I'm going to use when the server starts and the mongodb connection is established.
An ideal directory structure would be something like this:
mongodb
--schemas
----user.js
--models.js
You would put your schemas inside the schema folder, such as your User model:
(user.js)
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
module.exports = function() {
var UserSchema = new mongoose.Schema({
name: String,
email: String,
password: String,
age: Number
});
mongoose.model("User", UserSchema);
};
In models.js, you would have code that initializes each schema model in the schemas directory.
(models.js)
exports.initialize = function() {
require("fs").readdirSync(__dirname + "/schemas").forEach(function(file) {
require('./schemas/' + file)();
});
};
In your app.js file, you would do this call to initialize all your schemas AFTER you establish your connection to mongoose:
require($pathToYourModelsJsFile).initialize();
After this, you are all set to use your models! All you have to do for when you want to use them is:
var mongoose = require('mongoose');
var User = mongoose.model('User');
// Do work
User.find();

Abstracting Mongoose with Restify

I'm curious if anyone could provide some insight on the best way to abstract an API built with Node.js + Restify + Mongoose. After coming from an MVC / PHP background, it's interesting to find that there's not string/defined structure for Node applications.
As of now, I have my app.js file that auto loads my routes.js file, all model js files, etc.
The confusion is primarily in how my routes are supposed to interact with data from Mongo. Here is a basic rundown on how my code is layed out.
app.js:
/**
* Require Dependencies
*/
var restify = require('restify')
, mongoose = require('mongoose')
, config = require('./config')
, routes = require('./routes');
/**
* Create Server & Define Settings
*/
var server = restify.createServer({
name: config.name,
version: config.version
});
/**
* Common Handlers
*/
server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());
server.use(restify.jsonp());
/**
* Connect to Mongo Database
*/
mongoose.connect(config.mongo.uri, function(err) {
// assign connection to var so we can pass it down the chain
var db = mongoose.connection;
// handle connection error
db.on('error', console.error.bind(console, 'connection error:'));
// handle connection success
db.once('open', function callback () {
/**
* Start Routing API Calls
*/
routes.route(server, db);
});
});
/**
* Start Server & Bind to Port
*/
server.listen(config.port, function () {
console.log('%s v%s listening on port %s in %s mode.', server.name, server.version, config.port, config.env);
});
routes.js:
module.exports.route = function(server, db) {
var Users = require('./models/users.js');
/**
* Users
*/
server.get('/users', function (req, res, next) {
res.send(Users.list(db, req, res));
return next();
});
server.get('/users/:user_id', function (req, res, next) {
res.send(Users.get(db, req, res));
return next();
});
}
models/users.js:
// fake database
var users = [
{
name: 'Nick P',
email: 'nick#domain.com'
},
{
name: 'Zack S',
email: 'zack#domain.com'
}
];
exports.list = function(db, req, res) {
return users;
};
exports.get = function(db, req, res) {
return users[req.params.user_id];
};
As you can see, I'm using a "fake database" that is a simple object. Where / how could I introduce a Mongoose layer to communicate with our database? I'm mostly concerned with how I should use schemas and exports. Any code examples, or direction would be awesome.
Here a simple example of what I usually do with Express, it's kind of the same thing with Restify. You can manage your Mongoose schemas in the same way but in your Restify routes.
app.js :
var express = require('express');
var app = express();
app.configure(function () {
app.use(express.logger('dev'));
app.use(express.bodyParser());
});
// connection to mongoDB
var mongoose = require('mongoose');
mongoose.connect('mongodb:mongoURI');
var user = require('./routes/users');
app.get('/users/list', user.list);
app.listen(3000);
models/user.js :
var mongoose = require('mongoose')
,Schema = mongoose.Schema
,ObjectId = Schema.ObjectId;
var userSchema = new Schema({
id: ObjectId,
name: {type: String, default: ''},
email: {type: String, default: ''}
});
module.exports = mongoose.model('User', userSchema);
routes/users.js :
var User = require('../models/user.js');
exports.list = function(req, res) {
User.find(function(err, users) {
res.send(users);
});
};

Categories