Dumb question... I am working (i.e. learning) with an API in Node.js and connecting to MongoDB using the code below. Everything works great while the database code is located inside my routes.js file, but I would really like to move that code block out to a separate dbconfig.js file/module.
I've tried every method I can find, but the db variable/object always returns undefined when called inside my getQuery function. Any guidance would be greatly appreciated!!!
dbconfig.js
module.exports=function() {
var db;
var mongoClient = require('mongodb').MongoClient;
var mongoUrl = 'mongodb://username:password#ds123456.mongolab.com:123456/mydb';
var mongoOptions = {
server: {auto_reconnect: true}
};
getDb();
return {
db: this.db
};
function getDb() {
mongoClient.connect(mongoUrl, mongoOptions, function(error, database) {
if (error) {
console.log(error)
} else {
db = database;
}
});
}
};
routes.js (Relevant portion)
(function(routes) {
var dbconfig = require('.\dbconfig')();
var breezeMongo = require('breeze-mongodb');
var db = dbconfig.db;
function getQuery(request, result, next) {
try {
var resource = request.params.resource;
var collectionName = getCollectionName(resource);
var query = new breezeMongo.MongoQuery(request.query);
query.execute(db, collectionName, processResults(result, next));
} catch (ex) {
var err = {
statusCode: 404,
message: 'Unable to execute query " ' + request.url + '"',
error: ex
};
}
}
})(module.exports);
Related
I saw somewhere to do something you need to do something with db.eval, but node throw error that eval is not a function. I wanna execute string as mongo query. It DYNAMIC
const mongoClient = require("mongodb");
const url = "someurl";
const mongoClient = new MongoClient(url)
async function run() {
try {
await mongoClient.connect();
const db = mongoClient.db("somedb");
var query = "db.getCollection('somecollection').find().limit(1)";
db.eval('function(){ return ' + query + '.toArray(); }', function (err, res) {
console.log(res);
});
}catch(err) {
console.log(err);
} finally {
await mongoClient.close();
}
}
run();
I am creating api using Mongodb and nodeJS as a backend.I have created separate database connection file for that and trying to insert data in other file after importing database file in that.I have connect.js file in db folder and category.js file in routes folder.
But I am getting below error:
TypeError: Cannot read property 'db' of undefined
Below is my code:
connect.js
const MongoClient = require('mongodb').MongoClient;
const dotEnv = require('dotenv').config();
const url = process.env.URI;
const conn = () => {
MongoClient.connect(url,{useNewUrlParser:true,useUnifiedTopology:true})
.then((db) => {
}).catch((err) => {
console.log("error",err);
});
}
module.exports = conn;
category.js
const express = require('express');
const router = express.Router();
const conn = require('../db/connect');
router.get('/',(req,res) => {
data = { name:"Digvijay" };
conn().db("ExpDb").collection("Products").insertOne(data,(err,resp) => {
if(err){
console.log("Error",err);
}
else{
console.log("Success");
}
});
});
module.exports = router;
Someone let me know what I am doing wrong.
I am giving everything in the same file. You can segregate the as per requirement.
const MongoClient = require('mongodb').MongoClient;
// Connect to the db
MongoClient.connect("mongodb://localhost:27017/MyDb", function (err, db) {
data = { name:"Digvijay" };
db.collection('Products', function (err, collection) {
collection.insert(data);
db.collection('Products').count(function (err, count) {
if (err) throw err;
console.log('Total Rows: ' + count);
});
});
});
it might help to solve the issue.
https://docs.mongodb.com/manual/reference/method/db.collection.insert/#mongodb-method-db.collection.insert
compatible issue with insertOne:
https://docs.mongodb.com/manual/reference/method/db.collection.insertOne/#mongodb-method-db.collection.insertOne
Consider this code snippet below which is in the A.js file.
const connection = {};
mongo_cli.connect(url, (err, db) => {
...
connection['con'] = db;
});
module.exports = {
mongo:{
connection: connection['con'];
}
}
I do this const database = require('./A').mongo.connection; in B.js. A and B js files are in the same directory.
Why database variable in B file is undefined ?
That's because connection['con'] = db is in the execution context of the connect function callback. If you access connection['con'] from outside you're likely to get undefined. I suggest you to use Mongoose for such implementations. Here is a simple example:
const mongoose = require('mongoose');
const url = "your_mongodb_url";
const connect = mongoose.connect(url, {
useNewUrlParser: true
});
connect.then((db) => {
console.log('Database Connected');
}, (err) => {
console.log(err);
});
U won't get undefined if the connection succeeded. so for handling that , you can try something like this.
const connection = {};
connection['con'] = null;
mongo_cli.connect(url, (err, db) => {
...
connection['con'] = db;
});
module.exports = {
mongo:{
connection: connection['con']; // if connection failed then connection['con'] will be null.
}
}
This is a callback function:
(err, db) => {
…
connection['con'] = db;
}
It might get executed after the code that reads the database variable in B.js.
When I run the application, It shows me Database is connected!
db.js
var mysql = require('mysql');
var settings = require('./config');
var db;
var exports = {};
exports.connectdb = function () {
db = mysql.createConnection(settings.Database);
db.connect(function(err){
console.log('connecting');
if(!err) {
console.log('Database is connected!');
return db;
} else {
console.log('Error connecting database!'+err);
return null;
}
});
};
module.exports = exports;
but when i am trying to connect DB from user.js it shows me connection is null / TypeError: Cannot read property 'query' of undefined.
code block from user.js
var exports = {};
var dbcon = require('../config/db.js');
var dbconn = dbcon.connectdb();
exports.login = function(email,password) {
var userdetails = { name:email, password:password};
var dbconn = dbcon.connectdb();
if ( dbconn == null ) console.log('still nul');
dbconn.query("SELECT * FROM users where email = '"+email+"' and password = '"+password +"'", function (err, result) {
if(err)
{
console.log(result[0]+' err');
return null;
}
});
};
module.exports = exports;
Node.js is asynchronous by nature. You are trying to use it in a synchronous fashion. To make this work, you must use the callback pattern. Below is an example:
db.js
var mysql = require('mysql');
var settings = require('./config');
var exports = {};
exports.connectdb = function (callback) {
var db = mysql.createConnection(settings.Database);
db.connect(function(err){
callback(err,db);
});
};
module.exports = exports;
user.js
var exports = {};
var dbcon = require('../config/db.js');
exports.login = function(email,password) {
var userdetails = { name:email, password:password};
dbcon.connectdb(function(err, dbconn){
if ( err) //handle error
dbconn.query("SELECT * FROM users where email = '"+email+"' and password = '"+password +"'", function (err, result) {
if(err)
{
console.log(result[0]+' err');
}
});
});
};
module.exports = exports;
From the code above you can see how the connectdb function accepts a function callback. When the database is connected the code will execute that callback to send the results. In the user.js file, you can now pass a callback function and use the results it gives you (the db). You can find more info about Node.js' asynchronous nature here. Basically, asynchronous code uses callbacks and synchronous code uses return statements. Returning values from asynchronous functions will most always yield null results as asynchronous callbacks will always fire "sometime" after the function is called.
Im currently working on a NodeJS/Mongo project where I need to pull all the documents from a collection. I currently have the following code written:
var Db = require('mongodb').Db,
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server,
ReplSetServers = require('mongodb').ReplSetServers,
ObjectID = require('mongodb').ObjectID,
Binary = require('mongodb').Binary,
GridStore = require('mongodb').GridStore,
Grid = require('mongodb').Grid,
Code = require('mongodb').Code,
assert = require('assert');
var server = new Server('[server]', 27017);
var authDB = new Db('admin', server);
var DB1250 = new Db('1250', server);
var findDocuments = function (callback) {
authDB.authenticate("Username", "Password");
DB1250.open(function (error, db) {
if (error) {
console.log(error);
}
else {
console.log("successfully accessed: ", db);
callback;
var cursor = db.collection('Patients').find();
console.log('cursor ', cursor);
cursor.forEach(function (error, document) {
if (error) {
console.log('Document does not exist. Error: ', error);
}
else {
console.log('Document: ', document);
}
});
}
});
};
findDocuments(function (data) {
});
I am able to authenticate/connect to the server, connect to the DB, and connect to the collection. When I enter the forEach loop to iterate through all the documents, I keep getting the error "Callback is not a function". Can you guys see what I am doing wrong?
I believe the cursor you have there has not resolved into an array, so forEach is not a valid method. You might be looking for eachAsync, which will wait for the query to return before iterating.
Alternatively, you can wait for the query promise to resolve, ie:
cursor.then(docs => docs.forEach(callback));
which I personally find a little clearer.
Heres the solution I came up with after using Mongoose:
var Db = require('mongodb').Db,
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server,
ReplSetServers = require('mongodb').ReplSetServers,
ObjectID = require('mongodb').ObjectID,
Binary = require('mongodb').Binary,
GridStore = require('mongodb').GridStore,
Grid = require('mongodb').Grid,
Code = require('mongodb').Code,
Mongoose = require('mongoose');
assert = require('assert');
var findDocuments = function (callback) {
var options = { server: { socketOptions: { keepAlive: 1000 } } };
var connectionString = 'mongodb://username:password#server:27017/admin';
// Connected handler
Mongoose.connect(connectionString, function (err) {
var db = Mongoose.connection.useDb('db');
var collection = db.collection("collection");
collection.find().stream()
.on('data', function (document) {
console.log(document);
})
.on('error', function (err) {
// handle error
console.log(err);
})
.on('end', function () {
// final callback
});
});
// Error handler
Mongoose.connection.on('error', function (err) {
console.log(err);
});
// Reconnect when closed
Mongoose.connection.on('disconnected', function () {
self.connectToDatabase();
});
};
findDocuments(function () {
db.close();
});
cursor.forEach() is an asynchronous operation but returns nothing. So you shouldn't do db.close() or likewise below the line somethere synchronously.
Besides; I am not sure which version Node driver you are refering to but in the recent ones like v3+ cursor.forEach() doesn't take an error first type callback like the one that you use in your code. It will take an "iterator" and an "end" callback such as;
cursor.forEach(doc => console.log(doc),
err => err ? console.log(err)
: db.close())
So the above code will just work fine, iterating and processing the documents one by one as they appear without waiting up until all of them have been retrieved to the memory.