Stream from a mongodb cursor to Express response in node.js
I am toying around with all the fancy node.js/mongodb/express platforms, and stumbled across a problem:
app.get('/tag/:tag', function(req, res){
var tag=req.params.tag;
console.log('got tag ' + tag + '.');
catalog.byTag(tag,function(err,cursor) {
if(err) {
console.dir(err);
res.end(err);
} else {
res.writeHead(200, { 'Content-Type': 'application/json'});
//this crashes
cursor.stream().pipe(res);
}
});
});
As you probably guessed, catalog.byTag(tag, callback)
does a find()
query to Mongodb and returns the cursor
This leads to an error:
TypeError: first argument must be a string or Buffer
According to mongodb driver doc,
I tried to pass this converter to stream()
:
function(obj) {return JSON.stringify(obj);}
but that does not help.
Can anybody tell me how to correctly stream something to a response?
Or is the only solution a boilerplate to manually pump the data using the 'data' and 'end' events?
Use the cursor stream in combination with JSONStream
to pipe it to your response object.
cursor.stream().pipe(JSONStream.stringify()).pipe(res);
A working combination of other answers here
app.get('/comments', (req, res) => {
Comment.find()
.cursor()
.pipe(JSONStream.stringify())
.pipe(res.type('json'))
})
http://mongoosejs.com/docs/api.html#query_Query-cursor
-
cursor()
returns a Node streams3 compatible stream and is preferred over the deprecatedquery.stream()
interface. - Piping to
JSONStream.stringify()
to combine documents into an array instead of single objects - Piping to
res.type('json')
which sets the HTTPContent-Type
header toapplication/json
and returns itself (the response stream) again.
Simple. .stream({transform: JSON.stringify});