Поток из курсора mongodb в экспресс-ответ в node.js

Я играю со всеми фантастическими платформами 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) выполняет запрос find() к Mongodb и возвращает курсор

Это приводит к ошибке:

TypeError: first argument must be a string or Buffer

В соответствии с doc mongodb, Я попытался передать этот преобразователь в stream():

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

но это не помогает.

Может ли кто-нибудь сказать мне, как правильно передать что-то в ответ?

Или это единственное решение, позволяющее вручную накачивать данные с помощью событий "данных" и "конца"?

Ответы

Ответ 1

Рабочая комбинация других ответов здесь

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() возвращает поток, совместимый с потоками Node streams3, и является предпочтительным по сравнению с устаревшим интерфейсом query.stream().
  • Подключение к JSONStream.stringify() для объединения документов в массив вместо отдельных объектов
  • Настроить на res.type('json'), который устанавливает заголовок HTTP Content-Type в application/json и снова возвращает себя (поток ответов).

Ответ 2

Используйте поток курсора в сочетании с JSONStream, чтобы передать его в ваш объект ответа.

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

Ответ 3

Simple. .stream({transform: JSON.stringify});

Ответ 4

Ваш поток mongo сбрасывает объекты в поток res, который может обрабатывать только строки или буферы (следовательно, ошибка).

К счастью, потоки легко соединяются друг с другом, поэтому не слишком сложно сделать поток преобразования, чтобы укрепить ваши данные.

в node 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)

надеюсь, что поможет

Ответ 5

Использование мангуста и выражения:

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