我正在玩弄所有花哨的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);}
但这没有帮助。
有人可以告诉我如何正确地将某些内容流式传输到响应中吗?
或者是使用'数据'和'结束'事件手动泵送数据的样板的唯一解决方案?
答案 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();
});
}