How to use the MongoClient without coding "client.close()" every time? [duplicate] - javascript

This question already has answers here:
How do I manage MongoDB connections in a Node.js web application?
(13 answers)
Closed 3 years ago.
I try to package the db connecting for more reusable.
I want to achieve like :
const mongoPromise =MongoClient.connect(url,{ useNewUrlParser: true })
.then((client)=>{
const db = client.db(dbName);
// do something...
client.close();
})
.catch(err=>console.log(err));
Thus, I can use it to other places:
//For example
//query
mongoPromise.then((db)=>db.collection('user').find().toArray())
//insert
mongoPromise.then((db)=>db.collection('test').insert({...}))
When query or insert finished , the MongoClient will be close
At first method,I just can figure out a solution by mixing callback and promise.
Is it not good for mixing callback and promise together?
// First method
const mongoPromiseCallback =(callback)=>MongoClient.connect(url,{ useNewUrlParser: true })
.then(async(client)=>{
const db = client.db(dbName);
await callback(db);
console.log("close the client");
client.close();
})
.catch(err=>console.log(err))
mongoPromiseCallback(db=>db.collection('user').find().toArray())
.then(res=>console.log(res)));
At the other method,I try to use only promise,but I don't know
where can I close the client.
// the other method
const mongoPromise =MongoClient.connect(url,{ useNewUrlParser: true })
.then((client)=>{
const db = client.db(dbName);
return new Promise(function(resolve, reject) {
resolve(db);
});
})
.catch(err=>console.log(err));
mongoPromise.then(db=>db.collection('user').find().toArray())
.then(res=>console.log("res"));

You can always reuse the db object you created in mongo. Here read this it'll answer the question How do I manage MongoDB connections in a Node.js web application?

Related

Where and when to use knex.destroy? [duplicate]

This question already has answers here:
where to destroy knex connection
(3 answers)
Closed 7 months ago.
I'm confused on where to use knex.destroy() in my Node API.
If I don't use knex.destroy() after I open the connection to make a call, the connection pool fills up over time, leading to error:
Unhandled rejection TimeoutError: Knex: Timeout acquiring a connection. The pool is probably full. Are you missing a .transacting(trx) call?
If I close the connection, which makes sense to me, when I'm done with it,
router.get('/users', function(req, res, next) {
var select = knex.select('*').from('users');
select.then((result) => {
res.send(result);
}).catch((error) => {
res.send(error);
}).finally(function() {
knex.destroy(); // close it when I'm done
});
});
The connection is closed for separate API calls:
Unhandled rejection Error: Unable to acquire a connection
at Client_PG.acquireConnection (/var/app/current/node_modules/knex/lib/client.js:331:40)
So where and when do I actually destroy the connection? Again, this Node application simply serves as an API. Each API call should open, then close, the connection, but knex doesn't seem to like this.
Router files that require knex: (I do this for each router file)
const knexService = require('../knexService');
const bookshelf = knexService.bookshelf;
const knex = knexService.knex;
let User = require('../models/User');
module.exports = function(app, router) {
router.get('/users', function(req, res, next) {
var select = knex.select('*').from('users');
select.then((result) => {
res.send(result);
}).catch((error) => {
res.send(error);
}).finally(function() {
knex.destroy(); // close it when I'm done
});
});
...
UserModel file
const knexService = require('../knexService');
const bookshelf = knexService.bookshelf;
var BaseModel = require('./BaseModel');
var addressModel = require('./Address').Address;
var User = BaseModel.extend({
tableName: 'users',
hasTimestamps: true,
addresses: function() {
return this.hasMany(addressModel);
}
});
KnexService.js
const knexfile = require('./knexfile');
const knex = require('knex')(knexfile.production);
const bookshelf = require('bookshelf')(knex);
module.exports.knex = knex;
module.exports.bookshelf = bookshelf;
KnexFile.js
module.exports = {
development: {
client: 'pg',
version: '7.2',
connection: {
...
knex.destroy() should be called when you want to knex to throw away all connections from pool and stop all timers etc. so that application can end gracefully.
So basically that should be called only on application exit unless you are doing some more complex stuff for example with connecting to multiple databases with multiple knex instances.
If you are running out of connections and pool fills up it means that you have problems in your code. Possible reasons could be:
making too many long lasting queries concurrently
creating transactions and never committing / rolling back so those connections are never returned to the pool
bug in knex / bookshelf / some middleware
You should try to pinpoint which parts of your app causes pool to fill up, remove all the extra code like bookshelf related stuff and find the minimal setup which you can use to replicate your problem (also remove all transactions to start with).
Are you really using postgresql 7.2 or are you connecting some custom postgresql compatible DB? That could cause some issues, but I don't think those would reveal themselves in that way, but by having broken connections to be left in pool.

How to have only one mongodb instance?

Im writting a node app to log some informations in a mongo database.
Below is the snippet code that called each time i need to store log in the mongo database.
const mongo = {}
const mongo_cli = require('mongodb').MongoClient
module.exports = {
log (l) {
mongo_cli.connect(the_mongo_url, (error, client) => {
if (error) throw error;
mongo.cli = client;
mongo.db = client.db(the_database);
//insert and update operations
});
}
}
The code above work for now. I mean, I can insert and update logs already inserted at the price of one (or more) connection (s) that I never close due to my lack of control of callback functions.
So, how can i structure it better so that i can just have only one mongo_cli call to not consume too many ressources ?

I need get amount of documents in db (mongodb) [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Difference between count() and find().count() in MongoDB
(5 answers)
Closed 4 years ago.
I need get amount of documents in db (mongodb) . I tried get this value to my var like this:
var unique = collection.find({email: email}).count();
and like this:
var unique = collection.find({email: email}).toArray();
unique = unique.length;
But when I try to see this number in console, that show me 'undefined' :/
Whats wrong?
P.S sry for my english
From the docs. It's db.collection.count. Don't use find.
Returns the count of documents that would match a find() query for the
collection or view. The db.collection.count() method does not perform
the find() operation but instead counts and returns the number of
results that match a query.
Example Usage:
const MongoClient = require('mongodb').MongoClient;
// Connection url
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'users';
// Connect using MongoClient
MongoClient.connect(url, function(err, client) {
const db = client.db(dbName);
const email = 'foo#bar.com';
const query = { email: email };
const options = {};
db.collection.count(query, options, (err, result) => {
// handle error
if (err) {
console.log(err);
}
// do something with result
console.log(result);
});
});
Here is a basic example of how count might work. I assume you are using the mongodb npm and not mongoose or other mongo wrappers like it. The way I would use this in a project is by making the connection to your mongodb its own module so that it can be reused with other queries. That way you don't have to wrap every query with a connection.
If you want to get all the docs of a collection, use:
db.collection.count
If you want to get all the docs of a collection by a field, use:
collection.find({email: email}).toArray(function (err, items) {
console.log(items.length);
})

How to get list of databases in MongoDB using NodeJs? [duplicate]

This question already has answers here:
How to list all MongoDB databases in Node.js?
(5 answers)
Closed 6 years ago.
I have seen answers on C# and Java but not able to find anything on NodeJs. I have tried using cmd shell in Windows to get the required output but no luck.
I am aware that the same information can be taken in Mongo shell but the requirement is to get a list within the NodeJs app.
cmd = child_process.exec('"C:\\Program Files\\MongoDB\\Server\\3.2\\bin\\mongo.exe" admin ; db.getMongo().getDBNames()');
and also
var mongoServer = require('mongodb-core').Server;
var server = new mongoServer({
host: 'localhost'
, port: 27017
, reconnect: true
, reconnectInterval: 50 });
server.on('connect', function (_server) {
console.log('connected');
var cmdres = _server.command('db.adminCommand({listDatabases: 1})');
console.log("Result: " + cmdres);
}
You can use mongodb driver to get dbs as following
var MongoClient = require('mongodb').MongoClient;
// Connection url
var url = 'mongodb://localhost:27017/test';
// Connect using MongoClient
MongoClient.connect(url, function(err, db) {
// Use the admin database for the operation
var adminDb = db.admin();
// List all the available databases
adminDb.listDatabases(function(err, result) {
console.log(result.databases);
db.close();
});
});
Reference: http://mongodb.github.io/node-mongodb-native/2.2/api/
See this answer
db.admin().listDatabases

Basic node/mongo/mongoose connection not working

I'm new to MEAN stack development. I've created a database in MongoDB called 'framework' and a collection called 'users' with some json in. I can see that's all there and happy using mongo commands through Mac terminal.
Now I'm writing some Mongoose in my application and to test everything is working, I just want to get a list of the collection names. I tried this:
var mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/framework");
mongoose.connection.db.collectionNames(function (err, names) {
if (err) console.log(err);
else console.log(names);
});
But when I run that file through the command line, it doesn't log anything at all. What am I doing wrong here?
Make it as a callback function after the connection is successfully established. Without it being inside a callback method, it may get executed before the connection to the database is successfully established due to its asynchronous nature.
var mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/framework");
mongoose.connection.on('connected', function () {
mongoose.connection.db.collectionNames(function (err, names) {
if (err) console.log(err);
else console.log(names);
});
})
mongoose.connection.db.collectionNames is deprecated. Use this code to get the list of all collections
const mongoose = require("mongoose")
mongoose.connect("mongodb://localhost:27017/framework");
mongoose.connection.on('open', () => {
console.log('Connected to mongodb server.');
mongoose.connection.db.listCollections().toArray(function (err, names) {
console.log(names);
});
})
If you are not pretty sure of what should be the URL string for your mongoose.connect method. No worries, go to your command prompt, type mongo.
This starts the application where you can see the connection details like
Then use the same URL with your db-name appended like
const mongoose = require('mongoose');
mongoose.connect("mongodb://127.0.0.1:27017/db-name").then(
()=> console.log('connected to db')
).catch(
(err)=> console.error(err)
);
Hope this helps !!

Categories

Resources