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

时间:2013-11-18 21:46:29

标签: node.js mongodb 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 driver doc, 我试图将此转换器传递给stream()

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

但这没有帮助。

有人可以告诉我如何正确地将某些内容流式传输到响应中吗?

或者是使用'数据'和'结束'事件手动泵送数据的样板的唯一解决方案?

5 个答案:

答案 0 :(得分:20)

将光标流与JSONStream结合使用,将其传输到您的响应对象。

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

答案 1 :(得分:8)

此处其他答案的工作组合

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()返回与Nodestream3兼容的流,优先于已弃用的query.stream()界面。
  • 管道到JSONStream.stringify()以将文档合并到数组而不是单个对象
  • 管道到res.type('json'),将HTTP Content-Type标头设置为application/json并再次返回自身(响应流)。

答案 2 :(得分:6)

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

答案 3 :(得分:2)

您的mongo流正在将对象转储到res流中,该流只能处理字符串或缓冲区(因此错误)。

幸运的是,流很容易组合在一起,因此制作转换流并不太难以对数据进行字符串化。

节点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)

希望有所帮助

答案 4 :(得分:1)

使用mongoose并表达:

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