Express.js cannot connect to mongodb - javascript

Im on OS x. Im running an express.js app. This is what I have in app.js:
var express = require('express');
var mongoose = require('mongoose');
var cn = 'mongodb://localhost/test';
mongoose.connect(cn, function(error) {
console.log("inside?");
console.log(res);
});
console.log("outside");
If I open a terminal a write:
mongo
then I see this:
MongoDB shell version v3.4.3
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.3
Server has startup warnings:
2017-04-13T16:25:17.440+0200 I CONTROL [initandlisten]
2017-04-13T16:25:17.440+0200 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database.
2017-04-13T16:25:17.440+0200 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted.
2017-04-13T16:25:17.440+0200 I CONTROL [initandlisten]
> show dbs
admin 0.000GB
local 0.000GB
test 0.000GB
When I run
node app.js
The only thing I see in the terminal is:
outside
So it never goes inside "connect"? I have a callback because I realized that when I tried to communicate with database the code hangs up. I dont get any error message but it seems I never can query mongodb from express. What is wrong? I have tried several different connection string, for example 127.0.0.1 or even 127.0.0.1:27017 but no luck.

nothing wrong your code, you will get reponse after outside because node.js is not blocking the next code execution, once callback return the value you will get the output. its working for me.
var express = require('express');
var mongoose = require('mongoose');
var cn = 'mongodb://localhost/test';
mongoose.connect(cn, function(error) {
console.log("inside?");
console.log(error);
});
console.log("outside");
output console:
outside
inside?
undefined

Using 'async' or putting the connection initialization part inside a promise will make sure that the execution gets blocked till the connection has been made.
await mongoose.connect(cn, function(error) {
console.log("inside?");
console.log(res);
});
If you're using await make sure the function has the async keyword.
Using a promise:
return new Promise((resolve, reject) => {
mongoose.connection.on('open', () => {
debug('Connection successfully made');
resolve();
});
mongoose.connection.on('error', () => {
debug('Error occurred');
reject();
});
});

Related

Redis disconnection crashing node js server as well

After reading many stack overflow erros im still unable to solve this issue. I have setup a redis server to cache the data from my node js server , it works fine as long as the redis server is running but as soon as i close the redis server the node server crashes. i want the server to keep working even if the redis server is down
heres my code
import Product from '../models/productModel.js'
import User from '../models/userModel.js'
import slugify from 'slugify'
import redis from 'redis'
import mongoose from 'mongoose'
//connection to redis
const redisClient = redis.createClient(6379) //cause for error when redis server is down
export const listAll = async (req, res) => {
try {
const products = await Product.find({})
.limit(parseInt(req.params.count))
.populate('category')
.populate('subs')
.sort([['createdAt', 'desc']])
.exec()
if (products !== null) {
redisClient.setex(req.params.count, 60, JSON.stringify(products))
}
res.json(products)
} catch (err) {
console.log(err)
}
}
here im getting an ECONNREFUSED error when im stopping the redis server. Is there a way for my node server to keep going even when the redis server is stopped because redis servver is just a supporting mechanism and if cache data is unavailable ill anyway get data from db
is there a way to check if redisClient is undefined or null that i could set to check if the redis server is down and then later i can use it to make the request appropriately
According to the doc of node-redis Error Handling, have you try this ?
client.on("error", function(err) {
assert(err instanceof Error);
assert(err instanceof AbortError);
assert(err instanceof AggregateError);
// The set and get are aggregated in here
assert.strictEqual(err.errors.length, 2);
assert.strictEqual(err.code, "NR_CLOSED");
});

Trying to connect node.js to a mongodb, getting successful response but no connection

I have been following online instructions to set up a mongodb database using mongoose on node.js. I have managed to get the mongodb running and listening on port 27017, however when I run my connection code in node.js I get a successful response even when the mongo.db isn't running and I don't see any updates on the mongo.db to say it has received any data.
I have tried quite a few different examples from the internet but can't get any of them to work.
So I have my MongoDB saying:
2019-03-26T12:00:46.039+0000 I NETWORK [initandlisten] waiting for connections on port 27017
This is the basic code I am trying to get to work as my original API wasn't working:
//sample.js
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test', function(err){
if(!err) console.log('Successfully Connected');
console.log(mongoose.connection.host);
console.log(mongoose.connection.port);
});
I receive this response when I run
node sample.js
Successfully Connected
localhost
27017
But I receive this response even when my mongo.db has been shut down, so I think there is some error, I'm not sure how to check if they are connecting properly.
this works for me. try to set some debugging to find out what is happening.
mongoose.set('debug', true);
mongoose.connect("mongodb://localhost:27017/test", {useNewUrlParser: true})
.then(() => {
console.log('connected to the db');
})
.catch(err => {
console.log('connection failed ' + err);
});
I think you have to check the API to connect.
https://mongoosejs.com/docs/connections.html
Second parameter is option and third is callback - but u seem to have passed callback as second param - also, check what are you getting as response
mongoose.connect(uri, options, function(error) {
// Check error in initial connection. There is no 2nd param to the callback.
});
// Or using promises
mongoose.connect(uri, options).then(
() => { /** ready to use. The `mongoose.connect()` promise resolves to undefined. */ },
err => { /** handle initial connection error */ }
);

Testing Postgre Database on Heroku

I am currently building an API with Swagger on Heroku and i would like to try if the endpoints are creating the correct entries in the Postgre Database. However, once i try to connect to Heroku's Postgre in my testing envoirment the connection is rejected. I think this is because in the continous integration envoirnment heroku creates a sandbox and does not accept connections to the real dbs.
I tried to create a backup database as suggested here: https://devcenter.heroku.com/articles/heroku-postgres-backups
but i couldn't find the information to access!
Any help is appreciated!
Thank you.
Here is my code test:
'use strict';
var should = require('should');
var request = require('supertest');
var assert = require('assert');
var server = require('../../../app');
var pg = require('pg');
var knex = require('knex')({
client: 'postgresql',
connection: process.env.DATABASE_URL
});
describe('controllers', function () {
describe('testing cenas', function () {
it('test1', function (done) {
request(server)
.get('/hello')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
.end(function (err, res) {
assert.equal(res.body, 'Hello,Hugo Pereira!');
done();
});
});
});
});
it gives an error:
Unhandled rejection Error: Unable to acquire a connection
at Client_PG.acquireConnection (/app/node_modules/knex/lib/client.js:332:40)
at Runner.ensureConnection (/app/node_modules/knex/lib/runner.js:233:24)
at Runner.run (/app/node_modules/knex/lib/runner.js:47:42)
at Builder.Target.then (/app/node_modules/knex/lib/interface.js:39:43)
at testPg (/app/api/controllers/hello_world.js:27:44)
at swaggerRouter (/app/node_modules/swagger-tools/middleware/swagger-router.js:407:20)
at swagger_router (/app/node_modules/swagger-node-runner/fittings/swagger_router.js:31:5)
at Runner.<anonymous> (/app/node_modules/bagpipes/lib/bagpipes.js:171:7)
at bound (domain.js:301:14)
at Runner.runBound (domain.js:314:12)
at Runner.pipeline (/app/node_modules/pipeworks/pipeworks.js:72:17)
at Runner.flow (/app/node_modules/pipeworks/pipeworks.js:223:19)
at Pipeworks.flow (/app/node_modules/pipeworks/pipeworks.js:135:17)
at Pipeworks.siphon (/app/node_modules/pipeworks/pipeworks.js:186:19)
at Runner.<anonymous> (/app/node_modules/bagpipes/lib/bagpipes.js:98:22)
at bound (domain.js:301:14)
0 passing (2s)
The heroku pg:psql command should connect to your database. You can also pass it parameters to connect to alternative/backup databases.
If you are using a heroku postgres url then one thing you need for external access is the query string ?ssl=true appended to the url
e.g.
"DATABASE_URL" : "postgres://user:pass#ec2-54-235-206-118.compute-1.amazonaws.com:5432/dbid?ssl=true"
I manage to solve this problem using the heroku in-dyno database (https://devcenter.heroku.com/articles/heroku-ci-in-dyno-databases). Once i got the database I go to a endpoint in my dev env that i made myself that gives me a dump file of the schemas of my real db. In the test env i import this file and voila i have all the schemas and tables i need for my test envoirment.

create script to insert seed data into mongodb in node.js

I'm using mongoose and node.js (express), and I wish to insert seed data using script. Like when I do node scripts/createNotifications.js I can insert a data into my db.
My code
//createNotifications.js
const mongoose = require('mongoose')
const Notification = require('../api/models/notificationModel')
mongoose.Promise = global.Promise
module.exports = (async () => {
try {
const new_notification = await new Notification({
"userId" : mongoose.Types.ObjectId("5a3e76ce914e1d1bd854451d"),
"msg" : "Something"
}).save()
} catch(e) {
console.log('Error creating notifications. ', e)
}
})()
When I run the code I don't see any data been inserted. I have my server started in port 3000, do I have to connect to mongodb too in this file? since this file has nothing to do with my express app, it's just a separated file.
If you want to see this module running make sure the following
Make sure you've made connection with the database like mongoose.connect('mongodb://IP/DBName')
What you've posted above is just a module definition. It won't execute on its own. You'll have to require this module in your mail file, the file you're running with node for example node server.js and call the method. Something like
var notification = require(path/to/createNotifications);
notification();

node.js application - how to connect to mongodb and "share" connection via an include?

Background Information
I'm attempting my first node.js API/application. As a learning exercise, I'm trying to create some test cases initially delete all records in a table, insert 3 specific records, and then query for those 3 records.
Code
Here's the code I have cobbled together:
http://pastebin.com/duQQu3fm
Problem
As you can see from the code, I'm trying to put the database connection logic in a dbSession.js file and pass it around.
I am able to start up the http server by doing the following:
dev#devbox:~/nimble_node$ sudo nodejs src/backend/index.js
Server started and listening on port: 8080
Database connection successful
However, when I try to run my jasmine tests, it fails with the following error:
F
Failures:
1) The API should respond to a GET request at /api/widgets/
Message:
TypeError: Object #<MongoClient> has no method 'collection'
Stacktrace:
TypeError: Object #<MongoClient> has no method 'collection'
at resetDatabase (/home/dev/nimble_node/spec/resetDatabase.js:6:29)
at /home/dev/nimble_node/spec/e2e/apiSpec.js:23:25
at /home/dev/nimble_node/node_modules/async/lib/async.js:683:13
at iterate (/home/dev/nimble_node/node_modules/async/lib/async.js:260:13)
at async.forEachOfSeries.async.eachOfSeries (/home/dev/nimble_node/node_modules/async/lib/async.js:279:9)
at _parallel (/home/dev/nimble_node/node_modules/async/lib/async.js:682:9)
at Object.async.series (/home/dev/nimble_node/node_modules/async/lib/async.js:704:9)
at null.<anonymous> (/home/dev/nimble_node/spec/e2e/apiSpec.js:19:9)
at null.<anonymous> (/home/dev/nimble_node/node_modules/jasmine-node/lib/jasmine-node/async-callback.js:45:37)
Finished in 0.01 seconds
1 test, 1 assertion, 1 failure, 0 skipped
Database connection successful
Line 6 of resetDatabase is:
var collection = dbSession.collection('widgets');
Given that after the error appears, I get the "Database connection successful" message, I think what's happening is that when the tests request the dbSession library, the database hasn't finished running the code to connect. And therefore, I can't get the collection object.
I'm currently reading through the mongodb online manual to see if I can find some hints as to how to do something like this.
Any suggestions or pointers would be appreciated.
EDIT 1
To prove that there is a collection method on the MongoClient object, I changed the dbSession.js code to look like this:
'use strict';
var DBWrapper = require('mongodb').MongoClient;
var dbWrapper = new DBWrapper;
dbWrapper.connect("mongodb://localhost:27017/test", function(err, db) {
if (!err) {
console.log("Database connection successful");
dbWrapper = db;
var collection = dbWrapper.collection('widgets');
console.log('just created a collection...');
}
});
module.exports = dbWrapper;
And now, when I start up the http server (index.js), notice the messages:
dev#devbox:~/nimble_node$ sudo nodejs src/backend/index.js
Server started and listening on port: 8080
Database connection successful
just created a collection...
It could be an async issue.
Your code in dbSessionjs
dbWrapper.connect("mongodb://localhost:27017/test", function(err, db) {
if (!err) {
console.log("Database connection successful");
dbWrapper = db;
}
});
module.exports = dbWrapper;
Starts the connection at dbWrapper asynchronously, but exports dbWrapper right away, which is then imported in resetDatabase. Thus yes, the connect function may have not yet returned from the async function when you call it in resetDatabase (and is what the log suggests,as the error appears before the success log).
You could add a callback after dbWrapper.connect() returns, in order to actually only be able to use dbWrapper when the connection finished.
(With sqlite, this may not happen as it accesses the DB faster on the commandline).
This may not be your problem but looks like a candidate.
EDIT: Here's a possible example for a callback, but please take note it depends on what you need to do so there are a lot of different solutions. The key is to call a callback function when you are done initializing.
Another solution could be to simply wait, and/or poll (e.g. chcke a variable 'initialized').
'use strict';
var DBWrapper = require('mongodb').MongoClient;
var dbWrapper = new DBWrapper;
function doConnect(callback) {
console.log("Initializing DB connection...");
dbWrapper.connect("mongodb://localhost:27017/test", function(err, db) {
if (!err) {
console.log("Database connection successful");
dbWrapper = db;
var collection = dbWrapper.collection('widgets');
console.log('just created a collection...');
console.log('calling callback...');
callback(dbWrapper);
} else {
console.log("Error connectingi: " + err);
}
});
};
doConnect(function(correctDbWrapper) {
//Now you can use the wrapper
console.log("Inside callback, now consuming the dbWrapper");
dbWrapper = correctDbWrapper;
var collection = dbWrapper.collection('widgets');
});
It's interesting though I never ran into this issue, although I have generally used similar code like yours. I guess because normally I have this DB initialization right at the top, and then have to do lots of initializations on the node app, which gives the app time enough to return from the connect call....

Categories

Resources