So in the following functions I'm always establishing a new connection with my mongodb. How would I have to change my code so it only connects once at the beginning and not in every of these functions.
function getData(callback){
arrayOfArticles = [];
MongoClient.connect(url, { useNewUrlParser: true }, callback, function(err, db) {
if (err) throw err;
let dbo = db.db('testdb');
article = dbo.collection('testname').find({}).toArray(function(err, article) {
if (err) throw err;
db.close();
for (var i = 0, len = article.length; i < len; i++){
arrayOfArticles.push(article[i].name);
}
callback(null, arrayOfArticles);
});
});
function getPrice(callback){
arrayOfPrices = [];
MongoClient.connect(url, { useNewUrlParser: true }, callback, function(err, db) {
if (err) throw err;
let dbo = db.db('testdb');
article = dbo.collection('testcollection').find({}).toArray(function(err, arrayOfPrices) {
if (err) throw err;
db.close();
callback(null, arrayOfPrices);
});
});
function getDealerData(callback){
dealerData = [];
MongoClient.connect(url, { useNewUrlParser: true }, callback, function(err, db) {
if (err) throw err;
let dbo = db.db('Dealer');
article = dbo.collection('Dealer').find({}).toArray(function(err, dealerData) {
if (err) throw err;
db.close();
callback(null, dealerData);
});
});
It's not a good practice to create connection for every task.
I would suggest to create a separate file for create connection and available the connection on everywhere
Example
//db.js
MongoClient.connect(url, {
useNewUrlParser: true
}, callback, function (err, db) {
if (err) throw err;
global.dbo = db.db('testdb');
});
And in your main server file I am assuming app.js and require it on top for all middlewares
//app.js
<--All depandent module -->
require('db.js'); // change the path according to your structure.
And now dbo will be available to all your app and just use it everywhere.
It's also good practice to use single connection and for load, Mongo itself creates pull to handle the concurrency
As per Mongo official comment:
You open do MongoClient.connect once when your app boots up and reuse the db object. It's not a singleton connection pool each .connect creates a new connection pool. So open it once an reuse across all requests.
Update
I have tried to make your one function here
function getPrice(callback){
arrayOfPrices = [];
dbo.collection('testcollection').find({}).toArray(function(err, arrayOfPrices) {
if (err) throw err;
callback(null, arrayOfPrices);
});
}
I found this block of code, derived from the previous answer to be very useful...
Rather than a separate file it stores the collection in the app locals system.
MongoClient.connect(url, { useNewUrlParser: true })
.then(client => {
const dbo = client.db('myDB');
const collection = dbo.collection('numbers');
app.listen(port2, () => console.info(`REST API running on port ${port2}`));
app.locals.collection = collection; // this line stores the collection from above so it is available anywhere in the app, after small delay.
}).catch(error => console.error(error));
Related
I am new to JS. here is my function, so when I use this, it will return an empty list.
if I replace resultArray.push(result); with console.log(result); it will correctly show me the result.
I am expecting to see the function return the query result inside a list.
function queryMongo (key) {
var url = "mongodb://user:pw/task?replicaSet=bdb";
var resultArray = [];
// connect to the mongoDB
MongoClient.connect(url, { useUnifiedTopology: true }, function(err, db) {
if (err) throw err;
var dbo = db.db("task");
var query = { 'device' : key };
var cursor = dbo.collection('commands').find(query);
cursor.forEach(function(result){
if (err) throw err;
resultArray.push(result);
}, function(){
db.close();
})
});
return resultArray;
}
As shown in here one way would be to get the whole dataset at once:
async function queryMongo(key) {
var url = 'mongodb://user:pw/task?replicaSet=bdb'
// connect to the mongoDB
return new Promise(function (resolve, reject) {
MongoClient.connect(url, { useUnifiedTopology: true }, function (err, db) {
if (err) throw err
var dbo = db.db('task')
var query = { device: key }
// Fetch all results
dbo
.collection('commands')
.find(query)
.toArray(function (err, items) {
if (err) {
return reject(err)
}
resolve(items)
db.close()
})
})
})
}
async function doWork() {
// without "async" keyword it's not possible to "await" the result
console.log(await queryMongo('some-key'))
}
doWork();
Please take following advices into consideration:
Don't connect/disconnect at each function call aside if you're performing queryMongo() once in a while
The reason your code was not working is because you were returning the result before the async call was actually finished. Hence when doing queryMongo() result was straightly []. Indeed, establishing the connection to mongo and performing the query takes "time" and NodeJS will continue performing code execution while this is happening. I would advise to read a bit around the event loop to understand this mechanic a bit better.
I think that the main problem is that all db calls are asynchronous. You can't just return the value, you can pass to a callback or return Promise.
const MongoClient = require('mongodb').MongoClient;
function queryMongo(key, callback) {
const url = 'mongodb://localhost:27017';
MongoClient.connect(url, { useUnifiedTopology: true }, function(err, db) {
if (err) throw err;
const dbo = db.db('tasks');
const query = { device: key };
dbo
.collection('commands')
.find(query)
.toArray((err, doc) => {
if (err) throw err;
db.close();
callback(doc);
});
});
}
queryMongo(12, doc => {
/* do something */
console.log(doc);
});
1.I have a function that establish db connection and returns the connection object or the db handle.It is passed as an argument to other functions that use CRUD functions.Code is written in Node js file.
wrote two function one for db connection initiate and other to use the object returned by it
// function to return the db handle
function getDbConnection()
{
var dc;
MongoClient.connect(url, function(err, db) {
if (err) throw err;
return db;
});
}
// function to insert data
function CreatePost(dbo)
{
console.log(typeof dbo);
var mydbo = dbo.db("fb");
for(var i=0;i<25;i++)
{
postData = { pstID: ""+i, pstTitle: "Highway 37",pstTime: "100",pstdBy: "100",pstCntnt: "100"};
mydbo.collection("mypost").insertOne(postData, function(err, res) {
if (err) throw err;
console.log("1 document inserted");
dbo.close();
});
}
}
var dbo = getDbConnection();
CreatePost(dbo);
Error shown while executing
var mydbo = dbo.db("fb");
TypeError: Cannot read property 'db' of undefined
I am currently trying to learn how to use MongoDB. I tried two similar but slightly different pieces of code and received completely different results. I am trying to understand why this happened.
CODE 1
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017';
MongoClient.connect(url, { useNewUrlParser: true }, function(err, client) {
if (err) throw err
var db = client.db('EmployeeDB')
var cursor = db.collection('Employee').find()
cursor.forEach(function(err, doc) {
console.log(doc);
console.log("Hello")
});
client.close()
});
CODE 2
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017';
MongoClient.connect(url, { useNewUrlParser: true }, function(err, client) {
if (err) throw err
var db = client.db('EmployeeDB')
var cursor = db.collection('Employee').find()
cursor.forEach(function(err, doc) {
if (err) {
console.log(err)
} else {
console.log(doc);
}
});
client.close()
});
Code 1 returned "undefined \n undefined \n undefined". However, Code 2 returned the actual objects and their information. I was wondering why only the second piece of code works correctly.
There is only one argument in the callback of cursor.forEach(), not two. Hence in both cases, "doc" is not defined, and only "err" is defined (which is the actual document).
Your code should thus be:
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017';
MongoClient.connect(url, { useNewUrlParser: true }, function(err, client) {
if (err) throw err;
var db = client.db('EmployeeDB');
var cursor = db.collection('Employee').find();
cursor.forEach(function(doc) {
console.log(doc);
});
client.close();
});
From MongoDB official docs:
The signature includes a single argument that is passed the current document to process.
Source: https://docs.mongodb.com/manual/reference/method/cursor.forEach/
I'm beginner in nodeJS and I have some problems to manage asynchronous way of thinking.
I try to save data in my MongoDB Database and retrieve it. I get my data from a websocket service each 1 ms to 5 sec.
When it's each 5 sec there is no problem but each 1ms, when I display my collection content, the data are not already saved.
Here is my code :
// --Websocket event coming every 1 ms--//
while (1) { //Simulate Websocket events coming every 1 ms
dataBookSave(dataArrayfunction, function(log) { //array of data received from websocket event
console.log(log); //Display the callback log from the function dataBookSave
var query = ""; // Empty query in MongoDB to retrieve all data
mongoDb.find(dbName, collectionName, query, function(result) { // get all data from the MongoDB collection.
console.log(results); //Display all data from my MongoDB collection
});
}
}
function dataBookSave(dataArray, callback) {
if (dataArray.length < 1) callback("dataBookSave1"); //test if the array is empty. if yes, generate the callback
for (var i = 0; i < dataArray.length; i++) {
(function(i) { //closure the for loop
var objAdd = JSON.parse('{"data" : ' + dataArray[i] + ' }'); // create the object to add in the collection
mongoDb.insertCollection(dbName, collectionName, objAdd, function() { // insert function in MongoDB
if (i == dataArray.length - 1) // test if the loop is finished.
{
callback("dataBookSave2"); // if yes, generate the callback
}
});
})(i);
}
}
function insertCollection(dbName, collectionName, myObj, callback) {
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/" + dbName;
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbase = db.db(dbName);
dbase.collection(collectionName).insertOne(myObj, function(err, res) {
if (err) throw err;
db.close();
callback();
});
});
}
function find(dbName, collectionName, query, callback) {
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/" + dbName;
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbase = db.db(dbName);
dbase.collection(collectionName).find(query).sort({
_id: -1
}).toArray(function(err, result) {
if (err) throw err;
callback(result);
db.close();
});
});
}
I see when the for loop is executed, the asynchronous process iterate each data of the table and don't wait the insert database function to be executed. When the for loop is done, I read the collection in MongoDB. The problem is that data is still in queue, going to be written in the collection.
How can I resolve that? Give up with the async concept? Use closure? Find a best callback implementation?
You definitely don't want to connect/close the connection to your db every 1ms. Keeping the connection open is in this case recommended.
I haven't run the code bellow but it should work
var MongoClient = require('mongodb').MongoClient;
var url = "mongodb://localhost:27017/" + dbName;
var mongodb;
var collectionName = "some-collection";
MongoClient.connect(url, function(err, db) {
if (err) throw err;
mongodb = db;
run();
});
function run() {
// --Websocket event coming every 1 ms--//
while (1) { //Simulate Websocket events coming every 1 ms
dataBookSave(dataArrayfunction, function(log) { //array of data received from websocket event
console.log(log); //Display the callback log from the function dataBookSave
find(collectionName, function(result) { // get all datas from the MongoDB collection.
console.log(results); //Display all datas from my MongoDB collection
});
});
}
}
function dataBookSave(dataArray, callback) {
if (dataArray.length < 1) callback("dataBookSave1");
var arr = [];
// push object to arr for bulk insertion
for (var i = 0; i < dataArray.length; i++) {
arr.push({
data: dataArray[i]
});
}
insert(collectionName, arr, function() {
callback("dataBookSave2");
});
}
function insert(col, arr, callback) {
mongodb
.collection(col)
.insertMany(arr, function(err, res) {
if (err) throw err;
callback();
});
}
function find(collectionName, query, callback) {
mongodb
.collection(collectionName)
.find(query)
.sort({ _id: -1 })
.toArray(function(err, result) {
if (err) throw err;
callback(result);
});
}
I'm having trouble retrieving data from a mongodb collection which I believe has been inserted correctly.
So here is my example code...
var db = require('./database');
module.exports = function (app) {
app.get('/db', function (req, res) {
db.collection('myCollection', function (err, myCollection) {
if (err) {
return console.error(err);
}
var docrow = {
// no id specified, we'll let mongodb handle that
name: 'Mark',
date: '2013/09/11',
description: 'Some text here'
};
console.log('I GET HERE OK');
myCollection.insert(docrow, { safe: true }, function (err, insertedDocument) {
console.log('BUT I DONT GET HERE?');
if (err && err.name === 'MongoError' && err.code === 11000) {
return console.log('This document already exists');
} else if (err) {
return console.log('Something bad happened');
}
myCollection.find({ name: 'Mark' }, function (err, docs) {
docs.each(function (err, doc) {
console.log(doc);
});
});
});
res.end('OK we made it');
});
});
};
...and the database.js file is...
var Db = require('mongodb').Db,
Connection = require('mongodb').Connection,
Server = require('mongodb').Server;
var host = process.env['MONGO_NODE_DRIVER_HOST'] != null ? process.env['MONGO_NODE_DRIVER_HOST'] : 'localhost';
var port = process.env['MONGO_NODE_DRIVER_PORT'] != null ? process.env['MONGO_NODE_DRIVER_PORT'] : Connection.DEFAULT_PORT;
/*
w:1 tells mongo to wait until at least one confirmed write has succeeded before calling any callbacks
*/
var flags = { w: 1 };
var server = new Server(host, port, { auto_reconnect: true, poolSize: 20 });
var db = new Db('TestDBName', server, flags);
module.exports = db;
It looks like I'm able to create a Collection (myCollection) without error, and calling insert on the collection doesn't error either, but also doesn't appear to get any where near inside the callback function for it to trigger either an error or handle a success?
What am I doing wrong here?
Thanks for any help you can give me.
When you connect to mongodb it is asynchronous method, so it will return client handler in callback, and this client handler have to be used onwards instead of handle of that Db object. So change this:
var db = new Db('TestDBName', server, flags);
To this:
new Db('TestDBName', server, flags).open(function(err, client) {
if(err) throw err;
// client - is the guy you are looking for instead of `db` you had
});
As well change:
myCollection.find({ name: 'Mark' }, function (err, docs) {
To:
myCollection.find({ name: 'Mark' }).toArray(function (err, docs) {
It is the only exception with mongo-native where you have to use .toArray instead of direct callback.