Node Js: Exporting available Mongo database names doesn't work - javascript

I am struggling to export available Mongo databases to ./routes/index.js.
Related part of app.js:
var ACCESSIBLE_DATABASES = [];
var Db = require('mongodb').Db,
MongoClient = require('mongodb').MongoClient,
Server = require('mongodb').Server,
assert = require('assert');
var db = new Db('test', new Server('localhost', 27017));
db.open(function(err, db) {
var existing_databases = [];
var adminDb = db.admin();
// List all the available databases
adminDb.listDatabases(function(err, dbs) {
assert.equal(null, err);
assert.ok(dbs.databases.length > 0);
ACCESSIBLE_DATABASES = dbs.databases;
db.close();
});
});
// Code below export empty array
module.exports.accessible_databases = ACCESSIBLE_DATABASES;
// After some milisec the array has already contain the databases
setTimeout(function() {
console.log(ACCESSIBLE_DATABASES);
}, 100);
I'd like to avoid code repetition in my index.js file, but I couldn't achieve it. Import can't work either inside of 'adminDb.listDatabases' function nor later in 'setTimeout' function. (I'd like to use the result later in the app.js file so migrating the code into the index.js file is not an option.
I suggest the reason of it is the asynchronous code execution.

Since this involves async operations, the way you're trying to export wouldn't work. You'll have to pass a callback to get the databases once the operation has finished.
for eg.
function getDBs(db, adminDb, callback) {
// List all the available databases
adminDb.listDatabases(function(err, dbs) {
assert.equal(null, err);
assert.ok(dbs.databases.length > 0);
db.close();
callback(null, dbs);
});
}
function openHandler(callback) {
return function(err, db) {
var adminDb = db.admin();
getDBs(db, adminDb, callback);
}
}
module.exports.databases = function(callback) {
db.open(openHandler(callback));
}
// usage in routes/index.js
const dbs = require('./app').databases;
dbs(function(err, availableDBs) {
console.log(availableDBs);
});

You are exporting the accessible_databases object before it is initialized.
Try something like this:
var DB_OBJ = {};
adminDb.listDatabases(function(err, dbs) {
assert.equal(null, err);
assert.ok(dbs.databases.length > 0);
//export the array here
DB_OBJ.accessible_databases = ACCESSIBLE_DATABASES = dbs.databases;
db.close();
});
module.exports = DB_OBJ;
// After some milisec the array has already contain the databases
setTimeout(function() {
console.log(ACCESSIBLE_DATABASES);
}, 100);

Related

How to save a mongodb collection as array of documents

So, the problem is that I want to obtain data from a mongoDB collection to use it later in another piece of code. Are there any ways to obtain data from all documents in collection to work with them in javascript, without mongoDB library?
For now, I have some code:
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var ObjectId = require('mongodb').ObjectID;
var url = 'mongodb://localhost:27017/website';
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
console.log("Connected correctly to server.");
findGoods(db, function() {
db.close();
});
});
var findGoods = function(db, callback) {
var cursor = db.collection('goodsList').find( );
};
So, I found answer, to my question. I asked my friend about it, so if anybody needs code, here is it:
var findGoods = function(db, callback) {
var collection = db.collection('goodsList');
collection.find({}).toArray( function(err, docs) {
if (!err) {
console.log(docs)
} else {
console.error(err)
}
})
};

Returning queries from couchdb using nano

i've written a simple module to handle my couchdb CRUD operations using nano, however i'm having hardship returning from the results i query from the couch database. My Code is as follows.
couchdb.js
//Select from couch view
exports.couchSelect=function (_db, document,view) {
return _db.view(document, view,function(err, body){
if(!err){
var rows = body.rows; //the rows returned
console.log(rows);
return rows;
}else{
console.log(err);
}
}
);
}
routes.js
var couchdb = require('./couchdb');
app.get("/orders", function (req, res) {
var db = couchdb.couchConnect('ezyextension_orders');
var insert = couchdb.couchSelect(db, 'orders', 'orders');
console.log(insert);
});
On executing the returned output is only get Node http request parameters without the returned rows, need help to return the actual JSON rows queried.Thanx
You're using nano which use callback to make async calls. Returning _db.view only return a void function. I added comments to tell you what is happening :
exports.couchSelect = function(_db, document, view) {
_db.view(document, view, function(err, body) {
//This will be called after the couchSelect request.
if (!err)
console.log("Callback : " + body.rows);
});
}
//When you use it
var couchdb = require('./couchdb');
app.get("/orders", function(req, res) {
var db = couchdb.couchConnect('ezyextension_orders');
var insert = couchdb.couchSelect(db, 'orders', 'orders');
//This is synchronous. This will be called before the callback is called.
console.log(insert);
});
I decided to use blue-nano which uses promises instead of callbacks and the code is as below.
couchdb.js
var nano = require('nano-blue')('http://localhost:5984');
//Select from couch view
exports.couchSelect=function (_db, document,view) {
return _db.view(document, view);
}
routes.js
app.get("/orders", function (req, res) {
var db = couchdb.couchConnect('ezyextension_orders');
couchdb.couchSelect(db, 'orders', 'all').spread(function (body,header) {
res.send(body.rows);
}).catch(function(err) {
console.log(err.message);
});
});
This works perfectly

How to return JSON from MongoDB in Node.js?

I have a mongodb database called pokemon with a collection called pokemons. Here is my attempt to write a function that will do a find() operation in mongodb:
'use strict';
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
// db url
var url = 'mongodb://localhost:27017/pokemon';
exports.getPokemonByName = function (name) {
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
var cursor = db.collection('pokemons').find({name: name});
// how to return json?
});
};
I then call this function in another file:
var express = require('express');
var router = express.Router();
router.get('/pokedex', function (req, res) {
res.jsonp(db.getPokemonByName('Dratini'));
})
This link is helpful in showing how to log mongodb data to the console by doing some sort of each() method on the cursor object, but I don't know how to return json through the getPokemonByName function. I tried to define an empty array on the root scope of the getPokemonByName function and push data into that array with each iteration of the .each method show in that link, but I think I still can't return that array because it happens after the fact.
BTW, I'm really just doing this for fun and to learn about MongoDB and Node.js, so I don't want to use or an ODM like Mongoose to do some of this work for me.
I was able to answer my question with help from node's native monogodb driver github page: See here.
In essence, what I did was to define my exported function within the MongoClient's connection function. For some reason I thought node exports had to be in the root of the module, but that's not the case. Here's a finished version:
'use strict';
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
// db url
var url = 'mongodb://localhost:27017/pokemon';
var findDocuments = function(db, callback) {
// Get the documents collection
var collection = db.collection('pokemons');
// Find some documents
collection.find({name: 'Dratini'}).toArray(function(err, docs) {
assert.equal(err, null);
// assert.equal(2, docs.length);
console.log("Found the following records");
callback(docs);
});
}
// Use connect method to connect to the Server
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
console.log("Connected correctly to server");
findDocuments(db, function(docs) {
console.log(docs);
exports.getPokemonByName = function() {
return docs;
}
db.close();
});
});
And then in another file:
var express = require('express');
var router = express.Router();
router.get('/pokedex', function (req, res) {
res.jsonp(db.getPokemonByName());
});
Of course, this solution requires that I hardcode queries, but I'm okay with that for now. Will cross that bridge when I come to it.
Found a simple tweak for this. Let say the callback to the findOne returns result then you can convert the result to JSON object like this
result = JSON.parse(JSON.stringify(result))
Now you can access the result and its fields simply with the dot operator.
this may help
var cursor = db.collection('pokemons').find({name:name}).toArray(function(err,arr){
return arr;
});
You can use callbacks on find function to return the json.
Try
exports.getPokemonByName = function (name,callback) {
MongoClient.connect(url, function(err, db) {
assert.equal(null, err);
var cursor = db.collection('pokemons').find({name: name},function(err,result){
if(err)
{
callback(err,null);
}
if(result)
callback(null,result);
});
});
};
router.get('/pokedex', function (req, res) {
db.getPokemonByName('Dratini',function(err,result){
if(result)
{
res.jsonp(result);
}
});
})

Documents "disappearing" from mongodb collection after node loading routine is finished

Being new to mongodb and node, this particular issue is just driving me crazy:
I have written a small module, which reads an .csv file, makes it into a JSON array, and loads it into a mongodb collection one record at a time in a loop.
As I run this in debug, and set a breakpoint at "var v = i;" line, I can query the mongo collection, and see a fully populated records appear one after another.
However, as soon as the loop is finished - ALL records' data is gone!
The actual records are still all there, but they all empty. The data which I just saw in each record is no longer in those records.
It may be some wired scoping issue, but, being new, I just can not tell what that is.
Here is my code:
exports.excelFileParser = function(fileName, tabName, metadataFields){
var assert = require('assert');
console.log(metadataFields);
if(typeof require !== 'undefined') XLSX = require('xlsx');
var mongodb = require('mongodb');
var _ = require('underscore');
var fs = require('fs');
var Converter=require("csvtojson").core.Converter;
var distinctDataFields;
var MongoClient = mongodb.MongoClient;
var url = 'mongodb://localhost:27017/datamanager-03-test';
var fileName = 'clean_file.csv';
//fs.writeFileSync(fileName, newCsvLines);
var csvFileName=fileName;
var fileStream=fs.createReadStream(csvFileName);
//new converter instance
var csvConverter=new Converter({constructResult:true});
//end_parsed will be emitted once parsing finished
csvConverter.on("end_parsed",function(jsonObj){
//console.log(jsonObj); //here is your result json object
makeRecords(jsonObj);
});
function makeRecords(result){
console.log(result.length);
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
} else {
console.log('Connection established to', url);
var collectionName = 'DC_Facilities';
db.open(function(err, client){
client.createCollection(collectionName, function(err, col) {
});
var collection = db.collection(collectionName);
for(var i =0;i < result.length; i++){
var dataRecord = result[i];
collection.insert(dataRecord);
var v = i;
}
console.log("finished");
db.close();
});
}
});
}
fileStream.pipe(csvConverter);
};
collection.insert is an asynchronous function, so you're calling db.close() before any of them have a chance to complete. You also don't need to call createCollection as the collection will be created for you if it doesn't already exist.
So your code should look something like this instead, so that db.close() isn't called until all the insert operations have completed:
db.open(function(err, client){
var collection = db.collection(collectionName);
var inserted = 0;
for(var i = 0; i < result.length; i++){
var dataRecord = result[i];
collection.insert(dataRecord, function(err) {
if (++inserted == result.length) {
console.log("finished");
db.close();
}
});
}
});

Using Async queue to control DB connection request

I'm buidling an app with Node anb Mongodb Native. I'm working on a db module which i can require and call in other modules so that I end up using just one connection. The module db.js started out with this code:
var _db = null;
var getDb = module.exports.getDb = function(callback) {
if (_db) {
console.log('_db returned');
return callback(null, _db);
}
MongoClient.connect('mongodb://localhost:' + config.db.port + '/' + config.db.name, {native_parser: true}, function (err, db) {
if (err) return callback(err);
console.log('_db created');
_db = db;
callback(err, _db);
});
};
In my other modules that need a db connection I do this
db.getDb(function (err, connection) {
// Do something with connection
});
It works fine. But an unpleasant problem is that if my code would call getDb multiple times in a very short time span, I would end up with several copies of a connection. Like if I do my db.js requirements and getDb calls at the very beginning of all modules that need a db connection
I'm now thinking about controlling the calls to getDb by queuing them, so that only the absolute first call will create a connection and save it in _db. All later calls will get the created connection _db in return. I believe Async queue will help me with this...
The problem is that i dont understand how I write this with Async queue. The documentation is a little bit vague, and i dont find any better examples online. Maybe you can give me some hints. This is what i got so far...
var dbCalls = async.queue(function (task, callback) {
if (_db) {
console.log('_db returned');
return callback(null, _db);
}
MongoClient.connect('mongodb://localhost:' + config.db.port + '/' + config.db.name, {native_parser: true}, function (err, db) {
if (err) return callback(err);
console.log('Connected to mongodb://localhost:' + config.db.port + '/' + config.db.name);
_db = db;
callback(null, _db);
});
}, 1);
// I guess this .push() must be the exposed (exported) API for other modules to get a connection, but how do I return it to them,
dbCalls.push(null, function (err) {
console.log('finished processing foo');
});
dbCalls.push(null, function (err) {
console.log('finished processing bar');
});
I dont understand the object passed as first argument to .push() What should i use if for? Right now its null How do I pass on the connection and possible error all the way out to the module that made the call?
A quick and dirty solution without async.queue:
var _db = null;
var _err = null;
var _queue = [];
var _pending = false;
var getDb = module.exports.getDb = function(callback) {
if (_err || _db) {
console.log('_db returned');
return callback(_err, _db);
} else if (_pending) { // already a connect() request pending
_queue.push(callback);
} else {
_pending = true;
_queue.push(callback);
MongoClient.connect(..., function (err, db) {
_err = err;
_db = db;
_queue.forEach(function(queuedCallback) {
queuedCallback(err, db);
});
});
};

Categories