I want to use MongoDB connection object to different module. Problem is whenever my app.js run it should get instantiate then i can pass to other function of module.
Basically Mongo connection should be create only 1 time,
Currently i am using this code whenever we want to call MongoDb.How we can reuse MongoDb connection object outside of callback function.
var mongodb = require("mongodb");
mongodb.MongoClient.connect(url, function (err, db) {
if (err) {
console.log(err);
process.exit(1);
}
// Save database object from the callback for reuse.
console.log("Database connection ready");
});
//let say here i want to use
db.collection("cname").find({}) //but i am getting db as undefined.
The "false good idea" would be to use an other variable in the upper scope to store your db instance:
var mongodb = require("mongodb");
var dbInstance;
mongodb.MongoClient.connect(url, function (err, db) {
if (err) {
console.log(err);
process.exit(1);
}
// Save database object from the callback for reuse.
console.log("Database connection ready");
dbInstance = db;
});
// Here I don't know if dbInstance is define or not -> big problem!
Still, if this looks like a good idea, it's not. It will give you an error about dbInstance being undefined. mongodb.MongoClient.connect is async, so you'll need to wait for the callback before using "dbInstance".
It's better to use functions to which you'll pass the db instance as a argument:
var mongodb = require("mongodb");
var myModule = require("myModule")
var useDbInstance = function useDbInstance(dbInstance) {
//let say here i want to use
dbInstance.collection("cname").find({});
myModule(dbInstance)
.doSomething();
};
mongodb.MongoClient.connect(url, function (err, db) {
if (err) {
console.log(err);
process.exit(1);
}
// Save database object from the callback for reuse.
console.log("Database connection ready");
useDbInstance(db);
});
Then you could wrap you code in Promises to have a better control over the async flow and avoid the "callback hell".
I hope this helps :)
Related
I recently started working with the sqlite3 package in Node.js. Primarily I'm using the run, all and get functions. Since I like async/await more and those functions are taking callbacks, I used promisify from the util package to make them use promises that I can await.
import sqlite from 'sqlite3'
import { promisify } from 'util'
const db = new sqlite.Database('./myDatabase.db', (err) => {
if (err) {
return console.error(err.message);
}
console.log('Connected to the database.');
});
db.run = promisify(db.run)
db.all = promisify(db.all)
db.get = promisify(db.get)
This works with async/await however a problem shows up when I try to insert or update data using run().
const changedRows = await db.run("UPDATE races SET is_open = false WHERE code = ?", [racecode])
When I want to fetch the inserted ID or the affected rows I get undefined. That makes sense because the run function usually has no argument for a result thus resolve yields undefined.
From the docs:
db.run(`INSERT INTO langs(name) VALUES(?)`, ['C'], function(err) {
if (err) {
return console.log(err.message);
}
// get the last insert id
console.log(`A row has been inserted with rowid ${this.lastID}`);
});
The question is: Can I even get this.lastID from a promisified run ? I know there are some wrapper packages for sqlite3 out there, but I wanna try to use as few packages as possible before adding new ones.
I'm trying to follow this answer to connect to a mongodb atlas db from cloud functions.
I use this code from the answer above:
import { MongoClient } from 'mongodb'
const uri = 'mongodb://<USER>:<PASSWORD>#foo-shard-00-00-xxx.gcp.mongodb.net:27017,foo-shard-00-01-xxx.gcp.mongodb.net:27017,foo-shard-00-02-xxx.gcp.mongodb.net:27017/test?ssl=true&replicaSet=FOO-shard-0&authSource=admin&retryWrites=true'
let client
export default async () => {
if (client && client.isConnected()) {
console.log('DB CLIENT ALREADY CONNECTED')
} else try {
client = await MongoClient.connect(uri, { useNewUrlParser: true })
console.log('DB CLIENT RECONNECTED')
}
catch (e) {
throw e
}
return client
}
And then I have a function like this:
export const myFunction = functions.region('europe-west1').https.onRequest((request, response) => {
console.log(client.isConnected());
});
When I run firebase serve locally, I don't see 'DB CLIENT ALREADY CONNECTED' or 'DB CLIENT RECONNECTED' which means that anonymous function didn't get called. And when I try to access the client variable inside myFunction I get an error.
I'm learning Node at the moment so this might be a simple question. Thanks,
If you have some code to run in Cloud Functions, you need to invoke it. It's not possible to simply declare or export some function and expect it to run without calling it. If you want something to run at the global scope of your code, either don't wrap it in a function, or call the function at the global scope.
I have written node.js code for getting some number using mongodb database.this is my code for that
MongoClient.connect('mongodb://localhost:27017/mongomart', function(err, db) {
assert.equal(null, err);
var numItems=db.collection('item').find({"category":category}).count();
callback(numItems);
});
This mongodb query runs correct on mongo shell but it is giving error when using with node.js
Promise <Pending>
I don't know what is this "promise" ? Please help..
node.js code is asynchronous so that numItems won't contain count of items - it rather contains Promise that contains count of items when resolved. You defenetely have to master the basics of node.js and asynchronous programming. Try to modify your code like this
MongoClient.connect('mongodb://localhost:27017/mongomart', function(err, db) {
assert.equal(null, err);
db.collection('item').find({"category":category}).count()
.then(function(numItems) {
console.log(numItems); // Use this to debug
callback(numItems);
})
});
For native Promise check out documentation https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise
Also look at bluebird promises https://github.com/petkaantonov/bluebird
A promise is a substitute temporary value that is given while you wait on the real value. To get the real value do
numItems.then(function (value) { callback(value) });
Or better yet, return the promise from your function, and let they implement it using the Promises pattern, instead of the callback pattern.
Had the same problem. Don't know if it's still relevant to you, but this is what solved it for me:
var category = 'categoryToSearch';
var cursor = db.collection('item').find({'category':category});
cursor.count(function (err, num) {
if(err) {
return console.log(err);
}
return num;
});
I drove myself bananas trying to solve a similar problem, where the document.save() option just gave Promise{pending} no matter what I did. Here's what I did:
Change (req,res) to async(req,res).
Change var post = doc.save() to var post = await doc.save().
Finally, log in to MongoDB web, and change accessible IP addresses to 0.0.0.0 (all addresses). Not doing this can cause issues sometimes even when your IP is whitelisted.
try this:
MongoClient.connect('mongodb://localhost:27017/mongomart', async (err, db) => {
assert.equal(null, err);
var numItems= await db.collection('item').find({"category":category}).count();
callback(numItems);
});
(adding the await and turn this function to async function)
What is the best way to set up a singleton in Node for Mongodb? I tried the following code, but it does not work when making a lot of calls rapidly.
The singleton does not get set up before subsequent calls, and thus it tries opening too many connections and eventually fails. The below call works well for making infrequent calls.
Anyone have suggestions on the best practice here?
var db_singleon;
var getConnection= function getConnection(callback)
{
if (db_singleton)
{
callback(null,db_singleton);
}
else
{
var connURL = mongoURI; //set in env variables
mongodb.connect(connURL,function(err,db){
if(err)
console.error("Error creating new connection "+err);
else
{
db_singleton=db;
console.error("created new connection");
}
callback(err,db_singleton);
return;
});
}
}
node modules are singletons by theirselves, just make db module somewhere:
var mongo = require('mongojs');
var config = require('path/to/config');
var connection = mongo.connect(config.connection, config.collections);
module.exports = connection;
and then require('path/to/db') it in your models, etc.
I am using the node module jsonfile to read a json file and route it using the express module and res.json()
To my understanding I cant use the async read because manipulation of the json can only be handled in the callback making it effectively impossible to return the data and serve it using res.json()
app.get('/api/announcements', function(req, res) {
res.json(utils.getAnnouncements())
})
getAnnouncements: function() {
data = jsonfile.readFile('announcements.json', function(err, obj) {
//return obj
})
//return data
}
is what I want but in practice this either returns undefined or a promise depending on the implementation.
Would reading the file synchronously block the execution of the entire server or just the event loop of the app.get('/api/announcements')
Also, what would be the most correct way to go about doing this?
The entire Node process has a single event loop, so reading synchronously would block EVERYTHING. (clustering withstanding...)
You want to do something like:
app.get('/api/announcements', function(req, res) {
//define anonymous function that will be used when getAnnouncements is done.
utils.getAnnouncements(function(err,fileData){
// handle if(err)
res.json(fileData)
})
})
getAnnouncements: function(callback) {
//read file async, using callback function to handle results
jsonfile.readFile('announcements.json', function(err, fileData) {
callback(err, fileData)
})
//or just `jsonfile.readFile('announcements.json',callback)`
}