How do I send a Mongo Document back to the front end? - mongodb

//router
app.get('/retrieve_report', function(req, res) {
var retrieved = retrieve_report(req, res);
res.render('retrieve_report.ejs', {
'report' : retrieved
});
});
//Load up the report model
var Report = require('../models/report');
console.log('Report ' + Report.schema);
//expose this function to our app using module.exports
//query
module.exports = function(req, res) {
//console.log('param ' + res.send);
var query = Report.findById(req.param('id'), function(err, doc) {
if(err) {
throw err;
}
else {
console.log('doc ' + JSON.stringify(doc));
res.send(doc);
}
});
}
//app.js
var retrieve_report = require('./config/retrieve_report');//which is the above code
I want to return the document to the router so that I can put its information into my view. I tried "res.json(doc), but that gave me the error, "throw new Error('Can\'t set headers after they are sent.');" Everyone says to use a callback function, but aren't I using a callback function here?

As your error says:
but that gave me the error, "throw new Error('Can\'t set headers after they are sent.');"
Means you are trying to send data the twice.
Sample code:
app.get('/retrieve_report', function(req, res) {
var query = Report.findById(req.param('id'), function(err, doc) {
if(err) {
throw err;
}
else {
console.log('doc ' + JSON.stringify(doc));
res.send(doc);
}
});
This should work..

Related

Mongo db connection not establishing

Below is the code which i used to up the server. It is running in the localhost server 3000.
app.use('/', books);
app.listen(3000, function(){
console.log('Server running at port 3000: http://localhost:3000')
});
Below code throws mongodb error. Dont know what exactly the error. Below is my code
var express = require('express');
var router = express.Router();
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://127.0.0.1:27017';
// SHOW LIST OF BOOKS
router.get('/book', function(req, res, next) {
MongoClient.connect(url, function(error, db) {
if (error) throw error;
var dbo = db.db("BookStore");
dbo.collection("Books").find().toArray(function(err, result) {
if (err) throw err;
res.send(result);
console.log(result);
db.close();
});
});
});
// SHOW BOOK with ISBN
router.get('/book/:isbn', function(req, res, next) {
var isbn = parseInt(req.params.isbn);
MongoClient.connect(url, function(error, db) {
if (error) throw error;
var dbo = db.db("BookStore");
var query = { "isbn": isbn };
dbo.collection("Books").findOne(query, function(err, result) {
if (err) throw err;
res.send(result);
console.log(result);
db.close();
});
});
});
// Add BOOK
router.post('/book', function(req, res, next) {
MongoClient.connect(url, function(error, db) {
if (error) throw error;
var dbo = db.db("BookStore");
var myobj = {
"isbn":req.body.isbn,
"publisher":req.body.publisher,
"title":req.body.title,
"authors":req.body.authors,
"publishedDate":req.body.publishedDate,
"price":req.body.price
};
dbo.collection("Books").insertOne(myobj, function(err, result) {
if (err) throw err;
res.send('Book with '+req.body.isbn+' is successfully added');
db.close();
});
});
});
// UPDATE BOOK
router.put('/book/:isbn', function(req, res, next) {
var isbn = parseInt(req.params.isbn);
MongoClient.connect(url, function(error, db) {
if (error) throw error;
var dbo = db.db("BookStore");
var query = { "isbn": isbn };
var newvalues = { $set: {
"publisher":req.body.publisher,
"title":req.body.title,
"authors":req.body.authors,
"publishedDate":req.body.publishedDate,
"price":req.body.price
}
};
dbo.collection("Books").updateOne(query, newvalues, function(err, result) {
if (err) throw err;
res.send('Book with '+req.params.isbn+' is successfully updated');
db.close();
});
});
});
// DELETE BOOK
router.delete('/book/:isbn', function(req, res, next) {
var isbn = parseInt(req.params.isbn);
MongoClient.connect(url, function(error, db) {
if (error) throw error;
var dbo = db.db("BookStore");
var query = { "isbn": isbn };
dbo.collection("Books").deleteMany(query, function(err, result) {
if (err) throw err;
res.send('Book with '+req.params.isbn+' is successfully removed');
db.close();
});
});
});
module.exports = router;
Code Explanation:
We are creating a route to our application called 'Books.' So
whenever anybody browses to http://localhost:3000/books of our application, the code snippet defined for this route will be
executed.
Here we are getting all of the records in our 'Books'
collection through the db.collection('Books').find() command. We are then assigning this collection to a variable called cursor. Using this cursor variable, we will be able to browse through all of the records of the collection.
Run sudo mongod in the terminal
Is it impossible to connect even if you change the value assigned to the variable url to mongodb://[user_name]:[password]#127.0.0.1:27017/[your_database_name]?authSource=admin ?
Actually, the error is related to MongoDB version(MongoClient.connect(url, function(error, db)), MongoDB developers have changed their API. I don't know which version, it throws an error when you use MongoClient.connect(url, function(error, db).
So it should be MongoClient.connect(url, function(err, client)
Link to api-doc
And do not forget to run mongod

My mongoDB api is getting a webtask.io token error

I'm learning about webtask.io and so I've coded a simple REST api (I'm not using Express.js here but maybe I should). It's a little webtask.io app that connects to an mlab MongoDB database and retrieves todos from a tasklist collection. The issue is that I'm getting this error:
{"code":404,"message":"unable to resolve jtn to webtask token","req_id":"1504385487318.83712"}"
Any idea how to fix this error? Here is a snippet of my code:
var MongoClient = require('mongodb').MongoClient;
...
module.exports =
function (ctx, req, res) {
// write the header and set the response type as a json
res.writeHead(200, { 'Content-Type': 'application/json' });
MongoClient.connect(ctx.data.MONGO_URL, function (err, db) {
if (err) {
res.writeHead(400, { 'Content-Type': 'application/json'});
res.end(JSON.stringify(ERROR_RESPONSE.CONNECT_ERROR));
} else {
switch(req.method) {
case 'GET':
db.collection('tasklist').find({}).sort({"dateAdded" : -1}).toArray(function(err, docs) {
if (err) {
res.writeHead(400, { 'Content-Type': 'application/json'});
res.end(JSON.stringify(ERROR_RESPONSE.GET_ERROR));
} else {
res.end(JSON.stringify(docs));
}
}); //toArray
break;
//post, delete, and put are in here
} //switch
} //else no error
db.close();
}); //Mongo connect
res.end();
} //export function
I decided to try using Express and now I'm able to run my little webtask.io without having to have a web token. I'm not sure why my first try required one and if I find that answer I will post it. Here is my working version:
/* express app as a webtask */
var MongoClient = require('mongodb').MongoClient;
var Express = require('express');
var wt = require('webtask-tools');
var app = Express();
var assert = require('assert');
var ObjectId = require('mongodb').ObjectId;
app.use(require('body-parser').json());
function doCRUD (crudType,req,res) {
MongoClient.connect(req.webtaskContext.secrets.MONGO_URL,function (err, db) {
if (err) {
res.send(JSON.stringify(err));
} else {
switch(crudType) {
case 'GET':
db.collection('tasklist').find({}).sort({"dateAdded" : -1}).toArray(function(err, docs) {
if (err) {
res.send(JSON.stringify(err));
} else {
res.end(JSON.stringify(docs));
}
}); //toArray
break;
case 'POST':
db.collection('tasklist').insertOne({"tasklist" : req.query.todo, "dateAdded" : new Date()}, function(err, r) {
assert.equal(null, err);
assert.equal(1, r.insertedCount);
});
break;
case 'DELETE':
db.collection('tasklist').deleteOne({_id: new ObjectId(req.query.id)},function(err){assert.equal(null,err)});
break;
case 'PUT':
//not implemented for this hack
break;
}
}
});
}
// GET
app.get('*', function (req, res) {
doCRUD('GET',req,res);
});
// POST
app.post('*', function (req, res) {
doCRUD('POST',req,res);
res.end();
});
// DELETE
app.delete('*', function (req, res) {
doCRUD('DELETE',req,res);
res.end();
});
// expose this express app as a webtask-compatible function*/
module.exports = wt.fromExpress(app);
This error appears if you do not specify a valid path.
Try this one for example :
https://wt-666ohgod666ohgod666ohgod666ohgod-0.run.webtask.io/antidisestablishmentarianism666

Waiting for meteor cursor in method

I have a large aggrogate query that required me to pass "allowDiskUse: true" as an option. This would not work with the aggegate as described here:
https://github.com/meteorhacks/meteor-aggregate/issues/11
My meteor method is defined here. When I call the method I need to wait for ondata to complete before anything is returned to the client, but nothing I try allows me to get that data in a safe way up to the front end.
Meteor.methods({
'getSummary': function (dept,startDate,endDate,filterType) {
f = myQuery(startdate,enddate,dayFinalGroup);
f.on("data", Meteor.bindEnvironment(function(row) {
//load an array or something here to return
}));
f.once("end", Meteor.bindEnvironment(function() {
// tidy up, in my case end the stream
}));
//here I'd return the array loaded
},
});
This is my front end.
Meteor.call(
'getSummary',0,Session.get('start_date'),Session.get('end_date'),1,
function(error, result){
if(error){
console.log(error);
} else {
Session.set('sumTotals',result);
}
}
);
Finally Got it. I utilized wrapSync
'getSummary': function (dept,startDate,endDate,filterType) {
console.log(dept);
console.log(startDate);
console.log(endDate);
console.log(filterType);
var startdate = new Date(startDate);
var enddate = new Date(endDate);
var arr = [];
f = myQuery(startdate,enddate,dayFinalGroup);
var fetchCursor = Meteor.wrapAsync(function fetchCursor (cursor, cb) {
cursor.each(function (err, doc) {
if (err) return cb(err);
if (!doc) return cb(null, { done: true }); // no more documents
arr.push(doc);
});
});
var myData = fetchCursor(f);
return arr;

nightwatch custom command callback

I'm trying to create a custom command in nightwatch that runs a query on a Postgres database and returns the result. The query runs just fine and outputs the result to the console but then the execution of the test stops. I don't understand how callbacks work. How can I fix this custom command?
exports.command = function(sql, callback) {
var self = this;
var pg = require('pg');
var conString = self.globals.testinfo.connectionString;
var db = new pg.Client(conString);
db.connect(function(err) {
if(err) {
console.error('could not connect', err);
}
else {
db.query(sql, function(err, result) {
if(err) {
console.log('error running query', err);
}
else {
console.log(result.rows.length);
db.end();
}
});
}
}),
function(result) {
if (typeof callback === 'function') {
callback.call(self, result);
}
}
return this;
};
I had to wrap the database connection in a perform command to get this working. I'm not sure if this is the best way to handle the callback, but it works. Here's the updated version of the custom command:
exports.command = function(sql,callback) {
var self = this;
var pg = require('pg');
var cs = self.globals.testinfo.connectionString;
self.perform(function(self,done) {
pg.connect(cs,function(err,db,done) {
if(err) {
return console.error(err);
}
db.query(sql, function(err,result) {
done();
if(err) {
return console.error(err);
}
console.log(result.rows.length);
callback(result.rows[0]);
});
});
pg.end();
done();
});
};
Here's how I call the custom command in the test:
browser.myCustomCommand('select * from table limit 1;', function(row) {
browser.assert.deepEqual(row.column,'some value');
});
Can you try this:
exports.command = function(sql, callback) {
var self = this;
var pg = require('pg');
var conString = self.globals.testinfo.connectionString;
var db = new pg.Client(conString);
var cb= function(result) {
if (typeof callback === 'function') {
callback.call(self, result);
}
};
db.connect(function(err) {
if(err) {
console.error('could not connect', err);
cb(false);
}
else {
db.query(sql, function(err, result) {
if(err) {
console.log('error running query', err);
cb(false);
}
else {
console.log(result.rows.length);
db.end();
cb(true);
}
});
}
}),
return this;
};
And in your test :
'test' : function(browser){
browser.yourCommandName(sql,function(result){
console.log(result); //if connect is good result would be true and false if fail to connect.
});
}
Ps: the result in callback can be as an object(contain rows or anything you want), instead of boolean only in this example.
And Nightwatch is used for end-to-end testing, it is not aimed for Database testing,i think you should find another framework to test database connection.

How avoid "Can't set headers after they are sent."

I use mongodb and in mongodb I put my username and password.
The code is:
var mongodb = require('mongodb');
var http = require('http');
var fs=require('fs');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser());
app.listen(8080, function() {
console.log('Server running at http://127.0.0.1:8080/');
});
app.post('/prova', function(req, res) {
// res.send('You sent the name "' + req.body.username + '".');
var MongoClient = mongodb.MongoClient;
// Connection URL. This is where your mongodb server is running.
var url = 'mongodb://localhost:27017/utente';
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
} else {
//HURRAY!! We are connected. :)
console.log('Connection established to', url);
var collection = db.collection('login');
// var prova1=({name:"documento1",url:"sadsad",tag:"dc1"});
// do some work here with the database.
var cursor = collection.find();
cursor.each(function (err, doc) {
if (err) {
console.log(err);
} else {
// console.log('Fetched:', doc);
var username=0;
var password=0;
for(valore in doc){
if(valore!="_id"){
if(valore=="username"){
if(doc[valore]==req.body.username){
username=1;
}
}
if(valore=="password"){
if(doc[valore]==req.body.password){
password=1;
}
}
}
}
if(username==1 && password==1){
console.log("entra");
// res.end();
}else{
fs.readFile('C:\\Users\\Eventi\\Desktop\\Node.js\\Progetti\\ProveNodeJS\\NodeJSProve\\paginaRifiuto.html', function (err, html) {
if (err) {
}
res.writeHeader(200, {"Content-Type": "text/html"});
res.write(html);
res.end(html);
});
}
}
});
//Close connection
}
});
});
http.createServer(function(request, response) {
fs.readFile('C:\\Users\\Eventi\\Desktop\\Node.js\\Progetti\\ProveNodeJS\\NodeJSProve\\home.html', function (err, html) {
if (err) {
}
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.end();
});
}).listen(8000);
I call first http://localhost:8000 and I put in a text field the wrong value of username and password and after I click login I see my "login fail page" but I obtain this error:
Connection established to mongodb://localhost:27017/utente
_http_outgoing.js:335
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:335:11)
at ServerResponse.writeHead (_http_server.js:195:21)
at ServerResponse.writeHeader (_http_server.js:233:18)
at C:\Users\Eventi\Desktop\Node.js\Progetti\ProveNodeJS\NodeJSProve\HelloWord.js:67:23
at fs.js:334:14
at FSReqWrap.oncomplete (fs.js:95:15)