Does anyone know how to connect to MongoDb while using the Hapi.js framework?
I have only managed to find one example (https://github.com/Marsup/hapi-mongodb), but this requires using a plugin and has no comments in the code!
Does anyone know of a simpler way?
The following (using mongoose) works pretty well for me:
var Hapi = require('hapi');
var mongoose = require("mongoose");
var server = new Hapi.Server();
server.connection({ port: 3000 });
var dbUrl = 'mongodb://localhost:27017/mydb';
var dbOtions = {
db: { native_parser: true },
server: { poolSize: 5 }
};
server.register([ /* plugins */], function (err) {
if (err) {
throw err; // something bad happened loading the plugins
}
// ... Register the routes
server.start(function () {
mongoose.connect(dbUrl, dbOtions, function(err) {
if (err) server.log('error', err);
});
});
});
I use a hapi plugin that I wrote that connects to mongo, handles errors to log and adds bluebird promises.
'use strict';
var bluebird = require('bluebird');
var mongoose = bluebird.promisifyAll(require('mongoose'));
exports.register = function(plugin, options, next) {
mongoose.connect(options.mongo.uri, options.mongo.options, function (e) {
if (e) {
plugin.log(['error', 'database', 'mongodb'], 'Unable to connect to MongoDB: ' + e.message);
process.exit();
}
mongoose.connection.once('open', function () {
plugin.log(['info', 'database', 'mongodb'], 'Connected to MongoDB # ' + options.mongo.uri);
});
mongoose.connection.on('connected', function () {
plugin.log(['info', 'database', 'mongodb'], 'Connected to MongoDB # ' + options.mongo.uri);
});
mongoose.connection.on('error', function (e) {
plugin.log(['error', 'database', 'mongodb'], 'MongoDB ' + e.message);
});
mongoose.connection.on('disconnected', function () {
plugin.log(['warn', 'database', 'mongodb'], 'MongoDB was disconnected');
});
});
return next();
};
exports.register.attributes = {
name: 'mongoose',
version: '1.0.0'
};
Blog post on user authentication with passport and Mongoose
Also be aware that Hapi's model is based off of plugins so read and re-read the docs on building your own.
Visit http://cronj.com/blog/hapi-mongoose
Complete sample project which can help you Repo Link https://github.com/gauravgupta90/Hapi-Mongoose-Angular
Config.js
module.exports = {
server: {
host: '0.0.0.0',
port: 8000
},
database: {
host: '127.0.0.1',
port: 27017,
db: 'DatabaseName',
username: '',
password: ''
}
};
Server.js
var Hapi = require('hapi'),
Routes = require('./routes'),
config = require('./config'),
Db = require('./database');
var server = Hapi.createServer(config.server.host, config.server.port, {
cors: true
});
server.route(Routes.endpoints);
server.start(function() {
console.log('Server started ', server.info.uri);
});
Database.js
var Mongoose = require('mongoose'),
config = require('./config');
Mongoose.connect('mongodb://' + config.database.host + '/' + config.database.db);
var db = Mongoose.connection;
db.on('error', console.error.bind(console, 'connection error'));
db.once('open', function callback() {
console.log("Connection with database succeeded.");
});
exports.Mongoose = Mongoose;
exports.db = db;
The following works for me:
const Hapi = require("hapi");
const Mongoose = require("mongoose");
const server = new Hapi.Server({ "host": "localhost", "port": 3000 });
Mongoose.connect('mongodb://localhost:27017/testdb', { useNewUrlParser: true }, (err) => {
if (!err) { console.log('MongoDB Connection Succeeded.') }
else { console.log(`Error in DB connection : ${err}`)}
});
Related
I have uploaded a few images in MongoDB but cannot retrieve the images. I'm new to Next js, can anyone explain how I can make a "/api/retrieve?fileName='...'" get API to retrieve images from the database. The handler is being executed first then the db connection message is showing.
import nc from "next-connect";
import mongoose from "mongoose";
import Grid from "gridfs-stream";
import { GridFsStorage } from "multer-gridfs-storage";
export const config = {
api: {
bodyParser: false,
},
};
Grid.mongo = mongoose.mongo;
let gfs;
const conn = mongoose.createConnection(
process.env.mongoURI,
{
useNewUrlParser: true,
useUnifiedTopology: true,
},
(err) => {
if (err) {
console.err("file DB connection error", err);
process.exit();
}
console.log("file DB connected!");
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection("images");
}
);
export default async function handler(req, res) {
if (req.method === "GET") {
console.log("request query: ", req.query);
try {
const file = await gfs.files.findOne({ filename: req.query.filename });
const readStream = gfs.createReadStream(file.filename);
readStream.pipe(res);
} catch (error) {
res.send("not found");
}
}
}
Thanks in advance.
I am unable to load data(from MongoDB) to the handlebar template engine.when I console.log ArticleModel.find() its show data.But can't render data in the template engine.
Thanks in advance.
App.js
const handlebars = require("express-handlebars"); //Loads the handlebars module
let ArticleModel = require("./model/article");
var mongoose = require("mongoose");
var mongoDB = "mongodb://127.0.0.1/article";
mongoose.connect(mongoDB, { useNewUrlParser: true, useUnifiedTopology: true });
var db = mongoose.connection;
db.on("error", console.error.bind(console, "MongoDB connection error:"));
//Sets our app to use the handlebars engine
app.set("view engine", "hbs");
//Sets handlebars configurations (we will go through them later on)
app.engine(
"hbs",
handlebars({
layoutsDir: __dirname + "/views/layouts",
extname: "hbs",
partialsDir: __dirname + "/views/partials/"
})
);
app.use(express.static("public"));
app.get("/", function (req, res) {
ArticleModel.find({}, function (err, result) {
if (err) {
console.log(err);
} else {
res.render("main", { layout: "index", data: result });
}
});
});
//stating server
app.listen(PORT, () => {
console.log(`Server started at port ${PORT}`);
});
main.hbs
<h1>{{name}}</h1>
<ul>
{{#each data}}
<li>{{title}}</li>
{{/each}}
</ul>
I have this todo_list app built using:
Node.js
Express.js
EJS
MySQL
Choosing a database by following instructions from this Express website:
https://expressjs.com/en/guide/database-integration.html#mysql
https://expressjs.com/en/guide/database-integration.html#postgresql
I managed to make MySQL work with my todo_list app. But I'm having trouble refactoring the same CRUD (create) code for PostgreSQL use. Below is the working MySQL CRUD code and the unfinished PostgreSQL CRUD code for comparison. What am I doing wrong?
MySQL CRUD (create) code = works!
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static("public"));
// _____________________________________________________________________________
// Add new list item - MySQL
let mysql = require('mysql');
let connection = mysql.createConnection({
host: 'localhost',
user: 'dbuser1',
password: '12345',
database: 'testdb1',
});
app.post("/", function(req, res) {
const itemName = req.body.newItem;
let data = { name: itemName };
let sql = "INSERT INTO `todo_list` SET ?";
let query = connection.query(sql, data, function(err, results) {
if (err) throw err;
res.redirect('/');
});
});
PostgreSQL CRUD (create) code = doesn't work!
// .............................................................................
// Add new list item - PostgreSQL
// Loading and initializing the library without Initialization Options.
const pgp = require('pg-promise')();
const connection = {
user : 'pig1',
password : '12345',
host : 'localhost',
port : '5432',
database : 'todo_list'
};
// Database instance
const db = pgp(connection);
app.post("/", function(req, res) {
const itemName = req.body.newItem;
let data = { name: itemName };
let sql = "INSERT INTO todo_list SET ?";
db.any(sql, data)
.then(results => {
console.log(`Inserted data into database!`);
console.log('DATA:', results);
res.redirect('/');
})
.catch(error => {
console.log('ERROR:', error);
})
.finally(db.$pool.end);
});
Thanks for the pointers! #vitaly-t #rabhi-salim
I managed to make the CRUD (create) code work with PostgreSQL now.
app.post("/", function(req, res) {
const itemName = req.body.newItem;
let data = { name: itemName };
async function askStackOverflow() {
try {
await db.none('INSERT INTO todo_list(${this:name}) VALUES (${this:csv})', data);
// --- SUCCESS ---
console.log(``);
console.log(`Inserted data into database!`);
console.log(`DATA:`, insertedItem);
res.redirect('/');
} catch(error) {
// --- ERROR ---
console.log('ERROR:', error);
}
}
(async () => {
await askStackOverflow();
})();
});
Extra reading material:
Promises, Callback Hell, Async Await (ES7)
https://www.digitalocean.com/community/tutorials/javascript-promises-for-dummies
https://github.com/vitaly-t/pg-promise/wiki/Learn-by-Example#insert-with-result
https://www.npmjs.com/package/pg-promise#named-parameters
I have to get the MongoClient object from mongoose connection object, so that I can reuse for Agenda or somewhere else where I need.
db.js
// Export the mongoose instance
module.exports = () => {
mongoose.Promise = global.Promise;
try {
console.log('DBURL:', dbConfig.url);
const { url, options } = dbConfig;
mongoose
.connect(url, options)
.then(() => console.log('DB Connected'), err => console.log(err, options));
mongoose.connection.on('connected', () => {
logger.log('info', 'Mongoose default connection opened');
});
mongoose.connection.on('error', (err) => {
// logger.log('error', 'Couldn't able to connect to MongoDB', err);
// Blow system on db error
logger.log('info', 'Mongoose default connection opened');
throw err;
});
mongoose.connection.on('reconnected', () => {
logger.log('info', 'Mongo connection reconnected', arguments);
});
mongoose.connection.on('disconnecting', () => {
logger.log('error', 'Mongoose connection disconnecting', arguments);
});
mongoose.connection.on('disconnected', () => {
logger.log('error', 'Mongoose connection disconnected', arguments);
});
} catch (e) {
console.log("Couldn't connect to mongo:", e);
}
return mongoose;
};
You can get the mongoClient with getClient() method as shown in the docs: getClient()
Basically you need to do something like this
const client = mongoose.connection.getClient()
So to use it with connect-mongo for example you could just export that from your db.js then import and use where needed.
//db.js
module.exports.client = mongoose.connection.getClient()
//app.js
const { client } = require('path to file')
const store = MongoStore.create({ client })
const mongoose = require("mongoose");
let options = { //Your options };
const mongoClient = new mongoose.mongo.MongoClient(URI, options)
config = require('./configs');
mongoose = require('mongoose');
module.exports = function() {
var db = mongoose.connect(config.db, config.mongoDBOptions).then(
() => {
console.log('MongoDB connected')
},
(err) => {
console.log('MongoDB connection error',err)
}
);
require('../app/models/xxx.server.model');
require('../app/models/yyy.server.model');
return db;};
You may get MongoClient Object by following this method:
const { MongoClient, ObjectID } = require('mongodb');
function(req, res) {
(async function mongo() {
let client;
try {
client = await MongoClient.connect(url, {useNewUrlParser: true});
debug('Connected correctly to server');
const db = client.db(dbName);
}
I am beginner in Mean stack I am developing an API that fetches all records from mongodb using express. But I am not able to fetch all records from the database. I can't figure what I am doing wrong, I am doing it as follows:
This is my main app (server.js)
require('rootpath')();
var express = require('express');
var app = express();
var session = require('express-session');
var bodyParser = require('body-parser');
var expressJwt = require('express-jwt');
var config = require('config.json');
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
app.use(session({
secret: config.secret,
resave: false,
saveUninitialized: true
}));
// use JWT auth to secure the api
app.use('/api', expressJwt({
secret: config.secret
}).unless({
path: ['/api/users/authenticate', '/api/users/register']
}));
// routes
app.use('/', require('./controllers/login.controller'));
app.use('/register', require('./controllers/register.controller'));
app.use('/app', require('./controllers/app.controller'));
app.use('/api/users', require('./controllers/api/users.controller'));
/*// make '/app' default route
app.get('/', function (req, res) {
return res.redirect('/app');
});*/
// start server
var server = app.listen(3000, function() {
console.log('Server listening at http://' + server.address().address + ':' + server.address().port);
});
This is my user.controller.js user will make a request to the api
http://localhost:3000/api/users/userList
var express = require('express');
var router = express.Router();
var userService = require('services/user.service');
router.get('/userList', getUserList);
module.exports = router;
function getUserList(req, res) {
userService.userList()
.then(function(users) {
if (users) {
res.send(users);
} else {
res.sendStatus(404);
}
})
.catch(function(err) {
res.status(400).send(err);
});
}
This is my user.service.js where I am querying the database to fetch all records using mongoskin driver.
var Q = require('q');
var mongo = require('mongoskin');
var db = mongo.db("mongodb://localhost:27017/EmployeeForm", {
native_parser: true
});
db.bind('users');
var service = {};
service.userList = userList;
module.exports = service;
function userList() {
var deferred = q.defer();
db.users.find(function(err, users) {
if (err) deferred.reject(err.name + ': ' + err.message);
});
return deferred.promise;
}
So i think it's find issue.
MongoDB find method return cursor by default.
https://docs.mongodb.com/manual/reference/method/db.collection.find/
From https://github.com/kissjs/node-mongoskin they use method toArray which will transform cursor into array of objects like this
db.find.toArray(callback)
So try like this in userList()
function userList() {
var deferred = q.defer();
db.users.find({}).toArray(function(err,docs){
err ? deferred.reject(err) : deferred.resolve(docs);
});
return deferred.promise;
}
Hope this helps.