从mongodb游标stream到node.js中的Express响应

我在所有的花式node.js / mongodb / express平台上玩耍,偶然发现了一个问题:

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

正如你可能猜到的, catalog.byTag(tag, callback)对Mongodb执行find()查询并返回游标

这导致错误:

 TypeError: first argument must be a string or Buffer 

根据mongodb驱动程序文档 ,我试图通过这个转换器stream()

 function(obj) {return JSON.stringify(obj);} 

但是这并没有帮助。

任何人都可以告诉我如何正确地stream东西的响应?

还是唯一的解决scheme是使用“数据”和“结束”事件手动抽取数据的样板?

其他答案在这里工作的组合

 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()返回一个节点与streams3兼容的stream,并优先于不赞成的query.stream()接口。
  • pipe道到JSONStream.stringify()将文档组合到一个数组而不是单个对象
  • pipe道到res.type('json') ,它将HTTP Content-Type头部设置为application/json并再次返回自己(响应stream)。

使用与JSONStream组合的游标stream将其JSONStream到响应对象。

 cursor.stream().pipe(JSONStream.stringify()).pipe(res); 

简单。 .stream({transform: JSON.stringify});

您的mongostream将对象转储到只能处理string或缓冲区(因此错误)的resstream中。

幸运的是,stream很容易连接在一起,所以不难做出一个转换stream来将数据串联起来。

在节点v0.10.21中:

 var util = require('util') var stream = require('stream') var Transform = stream.Transform util.inherits(Stringer, Transform) function Stringer() { Transform.call(this, { objectMode: true } ) // 'object mode allows us to consume one object at a time } Stringer.prototype._transform = function(chunk, encoding, cb) { var pretty = JSON.stringify(chunk, null, 2) this.push(pretty) // 'push' method sends data down the pike. cb() // callback tells the incoming stream we're done processing } var ss = new Stringer() db.createObjectStreamSomehow() .pipe(ss) .pipe(res) 

希望有所帮助

使用mongoose和expression:

 function(req, res){ var stream = database.tracks.find({}).stream(); stream.on('data', function (doc) { res.write(JSON.stringify(doc)); }); stream.on('end', function() { res.end(); }); }