I started learning database with MongoDB and Node.js not long ago and I'm trying to find a way to use Express routes without mongoose. I want to insert data using Express routes and have clean code exporting different modules. The problem is that i can't write routes
as below because in my index.js file "db" is of course not defined and apparently i can't insert data into my "db" outside of the function "client.connect" as with mongoose. Do i have to connect my db in a file with all my posts or is there a specific way to do it? (sorry for my English, I'm learning it).
App.js :
const express = require('express');
const app = express();
const expressLayouts = require('express-ejs-layouts');
const MongoClient = require('mongodb').MongoClient;
const assert = require('assert');
//EJS
app.use(expressLayouts);
app.set('view engine', 'ejs');
//Styles
app.use('/public', express.static('public'));
//Bodyparser
app.use(express.urlencoded({extended: false}));
//Connect to DB
const url = 'mongodb://localhost:27017/shopping'
const dbName = 'shopping';
const client = new MongoClient(url);
client.connect((err)=>{
assert.equal(null, err);
console.log('connected to db...');
app.use('/', require('./routes/index'));
const db = client.db(dbName);
});
//Server
app.listen(3000, ()=>{console.log("Listening to port 3000")});
index.js (routes):
const express = require('express');
const router = express.Router();
//Get home page
router.get('/', (req, res)=>{
res.render('shop/index')
});
router.get('/posts', (req,res)=>{
res.render('posts')
});
router.post('/posts',(req,res)=>{
db.collection('users').insertOne({'name': req.name, 'password': req.password});
});
module.exports = router;
Index.js should include a function with which to pass your mongo client in. So for example:
let mongoClient
router.passMongoClient = function(clientIn){
mongoClient = clientIn
}
Then after you've started your client, pass it in through your new function
const router = require(./router)
client.connect((err)=>{
assert.equal(null, err);
console.log('connected to db...');
app.use('/', require('./routes/index'));
const db = client.db(dbName);
router.passMongoClient(db)
});
This is the basic idea. You may wish to structure your code a little differently. I wait to start my http server until I get the callback from the mongodb client that it's connected. Depends on your use case to a degree.
Related
Whenever I make a post request, it shows that message is not a constructor. Here message is a model that I made using mongoose.
And I am exporting this model through
module.exports = message and using this exported model in form_post.js file
my app.js file
const express = require('express');
const app = express();
const path = require("path");
const mongoose = require('mongoose');
const port = 3000;
const form_display = require('./routes/form_display');
const form_post = require('./routes/form_post');
app.use(express.urlencoded({ extended: false }))
app.use(express.json())
//Backend Connection
mongoose.connect("mongodb://127.0.0.1:27017/sudeepkart", {
useNewUrlParser: true,
useUnifiedTopology: true,
});
var db = mongoose.connection;
db.once("open", function () {
console.log("We are Connected !!");
});
// Pug Specific
app.set('view engine', 'pug') //Setting View Engine as Pug
app.set('views', path.join(__dirname, 'views')) //Setting views directory so that pug files can be fetched from he views directory
// Express Specific
app.use(form_display);
app.use(form_post);
app.use('/static',express.static('static'))
app.use((req, res, next)=>{res.status(404).send('<h2>Error Page Not found</h2>')});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
})
my form_post.js file
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Message = require('../models/message.model')
const port = 3000;
router.use(express.urlencoded({ extended: false }))
router.use(express.json())
router.post('/message', function (req, res) {
// Creating New Object
var newMsg = new Message(req.body);
newMsg.save(function (err, msg) {
});
res.send('Your message has been successfully submitted');
})
module.exports = router;
my models/message.model.js file
const mongoose = require('mongoose');
// New Schema and New Model
var message_schema = new mongoose.Schema({ "id":String, "message":String });
var message = new mongoose.model("message_model", message_schema); // in other words model is a synonym for collection
module.exports = message;
Try destructuring it:
const {message} = require('../models/message.models')
MDN Documentation for destructuring
To answer your comment question, because you're trying to import Message while only exporting message. On your module.exports, I would reccomend always doing module.exports = {variable1, function2} etc, so you can destructure it and you can easily debug any issues (and stop confusion with variables too!)
// app.js file
const express = require('express');
const morgan = require('morgan');
const courseRouter = require('./routers/courseRouter');
const app = express();
/// middleware
app.use(morgan('dev'));
app.use(express.json());
app.use((req,res,next)=>{
console.log('from middle ware');
next();
});
app.use((req,res,next)=>{
console.log('from second middle ware');
next();
});
/// routes
app.use('/courses',courseRouter);
module.exports = app;
//////////////// server.js file
const dotenv = require('dotenv');
const mongoose = require('mongoose');
const app = require('./app');
dotenv.config({path:"./config.env"});
mongoose.connect(process.env.DATABASE_LOCAL,{
useNewUrlParser:true,
useCreateIndex:true,
useFindAndModify:false,
useUnifiedTopology: true
}).then(con =>console.log(con.connections));
app.listen(3000,()=>{
console.log(` App running at port 3000`);
});
/////////////////courseRouter.js file
const express = require('express');
const courseController = require('./../controlers/courseController');
const router = express.Router();
router.
route('/courses').
get(courseController.getCourses);
module.exports = router;
//////// coursecontroller.js file
const Course = require('./../models/course.model');
exports.getCourses = async (req,res)=>{
try{
const courses = await Course.find({});
res.status(200).json({
status:'sucess',
data:{
courses
}
})
} catch (err){
console.log(err);
}
}
I'm trying to get simple get response from local mongoDB which is running at localhost:27017.
In there I have winrobot DB with collection courses which have one document.
So, my server is listening at port 3000, I have divided my routes , controllers and model according to MVC.
When I tried to get courses collection, I get "GET /courses 404 14.068 ms - 146" this morgan request log.but if I delete these controller and routes and implement that in app.js that works fine... so I want routes and controller in different files and still get courses collection.added the github repo of same code
You have this line:
app.use('/courses',courseRouter);
But then you are defining the router in the course file:
const router = express.Router();
router.
route('/courses').
get(courseController.getCourses);
Basically what ends up happening is you create a route that looks like:
/courses/courses/
You should change this:
router.
route('/').
get(courseController.getCourses);
Now your app will use the router you created properly.
I'm connecting to MongoDB from my Node.js.
If I start my connection from app.js file, then do I need to connect again from another JavaScript file, for example: from one of my models folder?
Here's my code for database.js:
const mongodb = require("mongodb");
const MongoClient = mongodb.MongoClient;
const mongoConnect = callback => {
MongoClient
.connect("mongodb+srv://<user>:<password>#node.idgpt.mongodb.net/myFirstDatabase?retryWrites=true&w=majority", {useUnifiedTopology: true})
.then(client => {
console.log("CONNECTED!!!");
callback(client);
})
.catch(err => {
console.log(err);
});
}
module.exports = mongoConnect;
Here's my code of app.js:
const path = require('path');
const express = require('express');
const bodyParser = require('body-parser');
const errorController = require('./controllers/error');
const mongoConnect = require('./util/database');
const app = express();
app.set('view engine', 'ejs');
app.set('views', 'views');
const adminRoutes = require('./routes/admin');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));
mongoConnect(() => {
app.listen(3000);
});
So, my question is: Do I need to connect to MongoDB through mongoConnect function every time I want to perform CRUD operation? For example: if I want to insert data from another file which is in models folder, do I need to connect to MongoDB first and then execute the insert operation, because I already first connect to MongoDB from my app.js and then I start listening to my node server.
Note: I have replaced my username and password with <user> and <password> respectively.
provide sample code for more insights.
but if you connect in one file you can require this file in many files, it will always be the same connection.
I've started learning on MEAN development. I had setup my express server and also my mongodb connection. On running node server in terminal the server starts running and also the mongo was able to connect but the localhost:8081/api/videos is not loading. I cleared cache and cookies but still no solution. I am attaching the code below.
server.js
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const api = require('./server/routes/api');
// Port for express server
const port = 8081;
const app = express();
app.use(express.static(path.join(__dirname,'dist/mean')));
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json);
app.use('/api', api);
app.get('*', (req,res)=> {
res.sendFile(path.join(__dirname, 'dist/mean/index.html'));
});
app.listen(port, function(){
console.log('Server running at localhost:' + port);
});
api.js
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const Video = require('../models/video');
// Creating mongo db connection
const db = 'mongodb+srv://<username>:<password>#training-qfjgb.mongodb.net/test?retryWrites=true&w=majority';
mongoose.Promise = global.Promise;
mongoose.connect(db, { useUnifiedTopology: true, useNewUrlParser: true }, err => {
if(err) {
console.log('Error: '+err);
}
else {
console.log('Successfully connected to mongodb');
}
});
router.get('/videos', function(req, res){
console.log('Get request for all videos');
Video.find({}).exec(function(err, videos){
if(err)
{console.log('Error retrieving videos');}
else
{res.json(videos);}
});
});
module.exports = router;
video.js (This is for the schema)
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Creating database schema
const videoSchema = new Schema({
title: String,
url: String,
description: String
});
// Creating model of database videoplayer as model and then exporting
module.exports = mongoose.model('video', videoSchema, 'videoplayer');
const db = 'mongodb+srv://username:password#training-qfjgb.mongodb.net/test?retryWrites=true&w=majority';
username:password should be changed.
admin:12345(as you using)
const db = 'mongodb+srv://username:password#training-qfjgb.mongodb.net/test?retryWrites=true&w=majority';
Check this part thoroughly , Whether the collection name, format of the text are given correctly
I have successfully generated and launched a nodejs application with express generator.This part is OK.
I have also created a standalone (single .js file) prototype of mongoDB setup (using mongoose - first time for me). OK
They do the job well but I am stuck when I combine the 2.
I assume my mistake is in the statements of module.exports but I can't figure out how to fix it.
Can anybody please help me to rewrite it?
nb I use "mongoose": "~5.3.16", (...if version is important ?)
My code (I skip some long parts):
/bin/www (for info, probably not the problem):
var app = require('../app');
var debug = require('debug')('api-dfv2:server');
var http = require('http');
const loadConfig = require('../public/javascripts/loadConfig.js');
const config = loadConfig.getConfig();
var port = normalizePort(config.port);
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
function normalizePort(val) {(I skip...)
}
function onError(error) {(I skip here some code to handle errors+event listener for http server "listening" event...)
app.js :
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var loadConfig = require('./public/javascripts/loadConfig.js');
var Conversation = require('./src/conversation');//declared but never read probably something wrong there
//the routers we need
var indexRouter = require('./routes/index');
var dfv2Router = require('./routes/dfv2');
//initiate express with moment
var app = express();
//link with moment module
app.locals.moment = require('moment');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
//app.set('view engine', 'jade');>>upgrade to pug
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
//let's load the initial config (or defaults)
//it will exit if no credentials are provided.
loadConfig.setConfig();
/**
* map the routes
*/
app.use('/', indexRouter);
app.use('/dfv2', dfv2Router);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
in dfv2.js, I receive POST requests from a chat system and I want to store that content in mongoDB :
var express = require('express');
var router = express.Router();
const conversation = require('../src/conversation')
/* POST received from chat system */
router.post('/', function(req, res, next) {
dialogflowv2.getDFResponse(req.body)//I generate the answer to the chat
.then((DFanswer) => {
console.log(JSON.stringify(DFanswer));//not a nice way to debug but it works until that point
var currentConversation = new conversation;
console.log('test5');
currentConversation = {"moment": "test"};//I should write the full mapping with the body etc. here just to test one field
console.log(JSON.stringify(currentConversation));
currentConversation.save() // THIS IS WHERE IT GOES WRONG XXXXXX
//.then(function(tmp) {console.log("ok : ",tmp)})
//.catch(function() {console.log("DB error :")})
res.status(200).json(DFanswer);
})
.catch(err => res.status(400).json(JSON.stringify(err.message)))
})
module.exports = router;
for info, conversation.js
var mongoose = require('mongoose');
const server = '127.0.0.1:27017'; // DB SERVER
const database = 'test_laurent'; // DB NAME
mongoose.connect(`mongodb://${server}/${database}`,{useNewUrlParser: true})
.then(() => {
console.log('Database connection successful - system ready')
})
.catch(err => {
console.error('Database connection error')
})
//get mongoose to use the global promise library
mongoose.Promise = global.Promise;
var db = mongoose.connection;
//to bind error of DB with console
db.on('error',console.error.bind(console, 'MongoDB connection error:'));
let mySchema = new mongoose.Schema(
{
body: String,
sessionId: String,
moment: String
})
let conversation = db.model('conversation', mySchema);
module.exports = conversation;
The result is that my DB doesnt receive anything. But it work well if I take all the code of conversation.js as standalone app (POST > generate schema > construct object > object.save > my collection is then created and visible in Compass so the DB and its connection is not the problem).
thank you in advance, any hint is welcome.
conversion is a constructor but you are not calling that when creating a new conversation.
Do this:-
const currentConversation = new conversation({moment: test});
Also .save() returns a promise so you have to await it so append a .then.catch block to .save method
currentConversation.save()
.then()
.catch()