Node.js/Postgresql database connection returns undefined - node.js

I have a PostgreSQL database hosted on Heroku. Here is how I connect to it:
//sql_conn.js
const pgp = require('pg-promise')();
pgp.pg.defaults.ssl = true;
const db = pgp('postgres://connection_string_redacted');
if(!db) {
console.log("Database setup unsuccessful.");
process.exit(1);
}
module.exports = db;
And I try to access it here:
//test-endpoint.js
const express = require('express');
const app = express();
const router = express.Router();
let db = require('../utils/sql_conn').db;
const bp = require('body-parser');
router.use(bp.json());
router.get("/", (req, res) => {
let query = "SELECT * FROM table;";
db.manyOrNone(query)
.then((rows) => {
res.send({
success: true,
result: rows
})
}).catch((err) => {
res.send({
success: false,
error: err
})
});
});
module.exports = router;
I have verified that the connection string is correct, the database is live on Heroku, and the path of the require statement is correct, but calling test-endpoint.js from the browser returns:
TypeError: Cannot read property 'manyOrNone' of undefined
Why is the database undefined?

It looks like an import/export problem. Try to replace this line:
let db = require('../utils/sql_conn').db;
by
const db = require('../utils/sql_conn');
And you should be fine.

Related

why am i getting Cannot read properties of undefined (reading 'collection') in the code below?

i'm new to mongodb and dev web and i'm using mongodb with nodejs in this project and i got this problem "Cannot read properties of undefined (reading 'collection')" on postman when i send a request but in VS it connect to database without any problem could anyone help me please
here is my code
that's my connection.js and here when i hover on collection and db it says in visual code it's undefined
const {MongoClient} = require('mongodb');
const {dbURL, dbName} = require('../config');
const client = new MongoClient(dbURL, {
useUnifiedTopology: true,
useNewUrlParser:true
});
function Connect(){
return new Promise(async(resolve, reject) =>{
try {
await client.connect();
const db = client.**db**(dbName);
const users = db.**collection**('users');
users.createIndex({email: 1},{unique: 1});
resolve(db, client);
}catch(error){
reject(error);
}
});
};
module.exports = Connect;
i hope someone can find the solution here
and this is my index.js
const Connect = require('./connection');
const {port} = require('../config');
const app = require('./app');
Connect().then(({db}) => {
app.setupRoutes(db);
console.log('The database is connected');
}).catch((e) => {
console.error("couldn't connect to database", e);
});
app.listen(port, () => console.log(`App listening on port ${port}!`));
module.exports = app;
and that's my app.js
as you see i'm using db.collection here
const express = require("express");
const cors = require("cors");
const ValidationError = require('./errors/ValidationError');
const app = express();
app.use(cors());
app.use(express.json());
const handleNewUser = (user, db) => {
return new Promise(async(resolve, reject)=>{
try {
const users = db.collection('users');
const results = await users.insertOne(user);
resolve(results.insertedId);
}catch (error){
reject(error);
}
})
};
app.setupRoutes = (db) => {
app.post('/users',async (req, res) =>{
const user = req.body;
try {
const errors = validateUser(user);
if(errors.length > 0) throw new ValidationError(errors, 'Validation Error');
const results = await handleNewUser(user, db);
res.status(201).send(results);
}catch (error){
if(error instanceof ValidationError)
res.status(500).send({message:error.message,errors:error.errors});
else if(error.message.startsWith('E11000 duplicate'))
res.status(500).send('duplicate email.');
else res.status(500).send(error.message);
}
});
}
module.exports = app;
i donét know what's wrong and i'm following a tutoriel
resolve(db, client) - you resolve not object but separate values "db" and "client".
Connect().then(({db}) => { -
tries to destructure the 'db' property of the first resolved value, and if your "db" value is not an object or doesn't have .db property, it would always be undefined.
So remove destructuring and use just the value:
Connect().then((db) => {

TypeError: Cannot read property 'db' of null

I am having issue connecting to mongodb atlas, getting the error below
let express = require('express')
let mongodb = require('mongodb')
let app = express()
let db
let connectionString = 'mongodb+srv://olumide:xxxxxxxx#cluster0-edskm.mongodb.net/todoApp?retryWrites=true&w=majority'
mongodb.connect(connectionString, {useNewUrlParser: true, useUnifiedTopology: true}, function(err, client){
db = client.db()
app.listen(3000)
})
app.use(express.urlencoded({extended: false}))
app.post('/create-item', function(req,res){
db.collection('item').insertOne({text: req.body.item}, function(){
res.send("thanks for submitting the form")
})
})
Error message
This is because the mongo.connect function is asynchronous. You will need to include the app.post function inside of the mongo.connect callback.
Something kind of like this should work:
let express = require('express')
let mongodb = require('mongodb')
let app = express()
app.use(express.urlencoded({extended: false}))
let connectionString = 'mongodb+srv://olumide:xxxxxxxx#cluster0-edskm.mongodb.net/todoApp?retryWrites=true&w=majority'
mongodb.connect(connectionString, {useNewUrlParser: true, useUnifiedTopology: true}, function(err, client){
const db = client.db()
app.post('/create-item', function(req,res){
db.collection('item').insertOne({text: req.body.item}, function(){
res.send("thanks for submitting the form")
})
})
app.listen(3000)
})
I figured out, in newer versions of MongoDB (3 and higher) they have essentially changed the way of connecting node server to the database. To establish a reusable connection (So that we can access the connected database from any other file), I created an async function in my db.js file where the connection is established and then exported it. In the end of the file, I have called the function. The code is as follows:
const {MongoClient} = require('mongodb')
const client = new MongoClient('mongodb+srv://todoAppUser:<password>#cluster0.6lvjr.mongodb.net/myDatabase?retryWrites=true&w=majority')
async function start(){
await client.connect()
console.log("Connected")
module.exports = client.db()
const app = require('./app')
app.listen(3000)
}
start()
and while calling it from another file:
const productCollection = require('./db').collection("product");
This code gives me no error and works perfectly fine. With the help of the above code, one can use this conveniently while following the MVC (Model-View-Controller) framework.
use mongoose connection as a different javascript file and import it to express script file
database.js
let mongoose = require('mongoose');
const server = '127.0.0.1:27017'; // REPLACE WITH YOUR DB SERVER
const database = 'test'; // REPLACE WITH YOUR DB NAME
class Database {
constructor() {
this._connect()
}
_connect() {
mongoose.connect(`mongodb://${server}/${database}`,{ useUnifiedTopology: true ,useNewUrlParser: true, useFindAndModify: false})
.then(() => {
console.log('Database connection successful')
})
.catch(err => {
console.error('Database connection error')
})
}
}
module.exports = new Database()
strong text

Cannot connect to MongoDB via env variable

I am trying to conceal my connection string, so I installed env2 in my project. Then I made a config.env file that keeps my connection string like this:
export DB_URL='mongodb://user:userPassword#ds241968.mlab.com:41968/heroku_hc9xjmcl'
However when I use that variable as a connection string I cannot connect to Mlab I get the following error:
UnhandledPromiseRejectionWarning: MongoNetworkError: failed to connect to server [ds241968.mlab.com:41968] on first connect [MongoError: Authentication failed.]
But when I try to connect only with the string without using env2 I connect perfectly, so why does the ahuthentication fail when I use a env variable and how can I connect with one properly? Here is my server.js:
// Requiring the dependencies
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const PORT = process.env.PORT || 3009;
const itemRoutes = express.Router();
let Comment = require('./comment.model');
const env = require('env2')('../config.env');
console.log(process.env.DB_URL)
app.use(cors());
app.use(bodyParser.json());
const { DB_URL } = process.env;
mongoose.connect( DB_URL , { useNewUrlParser: true } )
const connection = mongoose.connection;
connection.once('open', function() {
console.log('Connection to MongoDB established succesfully!');
});
// Serve static assets
if(process.env.NODE_ENV === 'production') {
app.use(express.static('build'));
}
itemRoutes.route('/').get( async (req, res) => {
let collection = connection.collection("posts");
let response = await collection.find({})
.toArray();
res.send(response);
});
itemRoutes.route('/comments').get( async (req, res) => {
let collection = connection.collection("comments");
let response = await collection.find({})
.toArray();
res.send(response);
});
itemRoutes.route('/userComments')
.post((req, res) => {
res.setHeader('Content-Type', 'application/json');
let comment = new Comment(req.body);
comment.save()
.then(comment => {
res.status(200).json({comment})
})
.catch(err => {
res.status(400).send('failed')
})
});
app.use('/', itemRoutes);
app.use('/userComments', itemRoutes);
app.listen(PORT, function() {
console.log('Server is running on' + ' ' + PORT);
})
Looks like you are using Node and Heroku. In that case,
You should set Heroku Config Vars (you can do this either via CLI or your Heroku Dashboard)
Refer to the config var in your node application the same way you are referring to now.
Remove 'env2' related code as you won't need it for this purpose
For example, if you create Heroku config var called "MONGO_URI", refer to it as process.env.MONGO_URI in your node application.
Details can be found here: https://devcenter.heroku.com/articles/config-vars#managing-config-vars

why does postman not recognize the "/:id" but instead throws an error?

i've managed to connect nodejs with postgresql. my problem is this, when trying to retrieve,delete or update a single item, the url '/v1/:id' is not recognized by postman.it throw a cannot get,or cannot delete or update error. but, retrieving all the user items works well. I'm not supposed to use any ORM but pure sql. I've also checked everywhere on the internet with no proper solution or explanation to this. What could be the issue?
//here is my app.js file
const express = require('express');
const bodyParser = require('body-parser');
const pg = require('pg');
const route = require('./routes/user');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:true}));
app.use('/v1',route)
module.exports = app;
//here is my controller file that handles the logic
const db = require('../db/config');
const getAllUsers = (req,res,next)=> {
db.query('select * from users',(err,result)=>{
if(err) {
res.status(400).send('error in connection')
}
res.status(200).json(result.rows);
console.log('this is the getusers route ')
})
}
const getUserById = (req,res,next)=> {
const id =parseInt(req.params.id);
db.query('select * from users where id=$1',[id],(err,results)=>{
if(err) {
throw err
}
res.status(200).send(results.rows);
console.log('successfully found id');
})
}
//delete item
const removeItem = (req,res,next)=> {
const id = parseInt(req.params.id);
db.query('DELETE from users where id=$1',[id],function(err,result){
if(err) {
throw err
}
console.log('item deleted');
})
}
module.exports = {getAllUsers,getUserById,removeItem}
//and here is my route file that handles all the routes
const express = require('express');
const router = express.Router();
const controller = require('../controller/user');
router.get('/',controller.getAllUsers);
router.get('/users/:id',controller.getUserById);
router.delete('/item/:id',controller.removeItem);
module.exports = router;
:id should be treated as URL parameter
http://localhost:8000/v1/users/1234 -> where 1234 is your :id
I'm using POST on my test
id parameter is empty, please enter "id" here
From the screenshot of postman, seems like you missed to set the value for "id" under path variable.

Node js & mongoDB - TypeError: db.collection is not a function

I am trying to post data from POSTMAN to an external database that I created on mLab but I am getting the error db.collection is not a function.
There is a similar question thread but the answer is incomplete and doesn't save any keys/values I put into postman to mLab. The code that I am trying to make work is from this tutorial: https://medium.freecodecamp.com/building-a-simple-node-js-api-in-under-30-minutes-a07ea9e390d2
My Code:
Server.js
const express = require('express'); // Load routes application
const MongoClient = require('mongodb').MongoClient; //Load database connection application
const db = require('./config/db');
const app = express(); // Assign express app a variable
const port = 8000; //Set local port value for server
const bodyParser = require('body-parser'); // **This has to come BEFORE routes
var assert = require('assert'); // ?
var databaseURL ='mongodb://external:api#ds123312.mlab.com:23312/soundfactory';
app.listen(port, () => {
console.log('')
console.log('We are live on ' + port);
console.log('')
});
MongoClient.connect(databaseURL, function(err, db) {
assert.equal(null, err);
console.log("API has succesfully connected to Sound Facotry mlab external database.");
console.log('')
db.close();
});
app.use(bodyParser.urlencoded({ extended: true }))
require('./app/routes')(app, {}); //Must come AFTER express w/ body parser
db.js
module.exports = {
url : 'mongodb://external:api#ds123312.mlab.com:23312/soundfactory'
};
index.js
const noteroutes = require('./note_routes');
module.exports = function(app,db)
{
noteroutes(app,db);
};
note_routes.js
module.exports = function(app, db) {
app.post('/notes', (req, res) => {
const note = { text: req.body.body, title: req.body.title };
db.collection('notes').insert(note, (err, result) => {
if (err) {
res.send({ 'error': 'An error has occurred' });
} else {
res.send(result.ops[0]);
}
});
});
};
partially correct code
server.js (code that partially works & doesn't throw the db.collections error like my original server.js file )
const express = require('express');
const MongoClient = require('mongodb').MongoClient;
const bodyParser = require('body-parser');
const db = require('./config/db');
const app = express();
const port = 8000;
app.use(bodyParser.urlencoded({extened:true}));
MongoClient.connect(db.url,(err,database) =>{
if (err) return console.log(err)
//require('./app/routes')(app,{});
//check below line changed
require('./app/routes')(app, database);
app.listen(port,() => {
console.log("We are live on"+port);
});
})
Remove the node_modules folder and change mongodb version of your package.json
"mongodb": "^2.2.33"
and run below code :
npm install
change to this require('mongodb').MongoClient;

Resources