Returning queries from couchdb using nano - javascript

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

Related

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

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);

Sending MongoDB results with Node

I use the following very basic script create a server:
var http = require('http');
var queryResult = '';
const PORT=8080;
function handleRequest(request, response){
fetchResult("user1"); //string is a placeholder, but works for now
setTimeout(function() {
// **POSSIBLE SOLUTION SPOT A**
response.end("some text");
}, 1000);
}
var server = http.createServer(handleRequest);
server.listen(PORT, function(){});
I've broken this up just because I think its easier to read. But on the same page I also the following:
var mongodb = require('mongodb');
var MongoClient = mongodb.MongoClient;
var url = 'mongodb://localhost:27017/my_database_name';
function fetchResult(query){
MongoClient.connect(url, function (err, db) {
if (!err) {
var collection = db.collection('users');
collection.find({name: query}).toArray(function (err, result) {
if (result.length)
queryResult = result;
// **POSSIBLE SOLUTION SPOT B**
db.close();
});
}
});
}
This works. It result is an object that has values from my database. And the server is able to write "some text" when someone makes a request. However, I can't get it so that the object is written onto the page or otherwise transferred when the user makes the request. What is the best way to do this?
Notes:
1) I know that using the timeout here is INSANELY bad. I couldn't figure out how to make the callback work properly and it works well enough for this example. I'll play through that myself issue once I solve the issue I've described above.
2) I think that JSON.stringify() may play a role in this, but I cant figure out what to do with it.
3) I don't want to use any other module (like express) just yet. I'm trying to understand how I would achieve the desired result with just the http module.
I think this is the Frankenstein code you're trying to write:
var http = require('http');
var mongodb = require('mongodb');
const PORT=8080;
var MongoClient = mongodb.MongoClient;
var url = 'mongodb://localhost:27017/my_database_name';
function handleRequest(request, response){
fetchResult("user1");
MongoClient.connect(url, function (err, db) {
if (!err) {
var collection = db.collection('users');
collection.find({name: query}).toArray(function (err, result) {
if (result.length)
response.end(JSON.stringify(result));
db.close();
});
}
});
}
var server = http.createServer(handleRequest);
server.listen(PORT, function(){});
As you said yourself, don't use this in production - it's a messy, unreadable blob. setTimeout has been removed because I'm not sure what you were trying to accomplish with it.

Node.js variable use outside of function

I'm trying to make it so that I can pass my trends variable from its function into a renderer for my Pug template, and I can't seem to do it.
var express = require('express');
var router = express.Router();
var googleTrends = require('google-trends-api');
var auth = require('http-auth');
var ustrends;
var uktrends;
const Console = require('console').Console;
var basic = auth.basic({
realm: "Web."
}, function (username, password, callback) { // Custom authentication method.
callback(username === "user" && password === "pass");
}
);
var find = ',';
var regex = new RegExp(find, 'g');
googleTrends.hotTrends('US').then(function(trends){
ustrends = trends
});
googleTrends.hotTrends('EU').then(function(trends1) {
uktrends = trends1
});
console.log(ustrends);
/* GET home page. */
router.get('/', auth.connect(basic), function(req, res, next) {
res.render('index', {trends: ustrends.toString().replace(regex, ", "), trends1: uktrends.toString().replace(regex, ", "), title: 'Trends in the U.S & U.K'});
});
module.exports = router;
As you can see, I'm trying to pass the "ustrends" and "uktrends" variables into the renderer. Any help is appreciated.
Remember that hotTrends will return a promise, as it's getting results from Google's API. Since the renderer is outside of the callbacks wherein ustrends and uktrends are set to values, there's no guarantee these values will be set prior to the renderer being called.
You could use several nested callbacks, but that would lead to some code pushed pretty far to the right; I recommend the async library, which has a function called series that allows you to pass in 1) an array of functions to be executed in order and 2) a callback that will be executed after the functions have completed that takes an error if there was one and the result of the functions as an argument. In the snippet below, the trends API returns results prior to the renderer being called:
async.series([
function(cb) {
googleTrends.hotTrends('US').then(function(trends){
ustrends = trends;
cb();
})
},
function(cb) {
googleTrends.hotTrends('EU').then(function(trends1) {
uktrends = trends1;
cb();
});
}
], function(err, results) {
/* handle errors, do rendering stuff */
})

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);
}
});
})

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