2011-09-10 3 views
24

私は、MongoDBクエリの結果をnodejsクライアントにストリーミングする方法の例を探しています。私が今までに見つけたすべての解決策は、クエリ結果を一度に読み取ってから、結果をサーバーに送り返すようです。nodejsでMongoDBのクエリ結果をストリーミングする方法は?

代わりに、私は(明らかに)クエリメソッドにコールバックを提供し、MongoDBが結果セットの次のチャンクが利用可能になったときに呼び出すようにしたいと思います。

私はおそらく別のドライバーを使用すべきでしょうか?

答えて

25

ストリーミング

Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream); 

よりは一例で、そのdocumentation pageで見つけることができる詳述:マングースにこの質問を投稿した後three monthsが登場バージョン2.4.0で利用可能となりました。

+8

'mongoose:Query.prototype.stream()は、mongoose> = 4.5.0ではなく、代わりにQuery.prototype.cursor()を使用します。 ' –

9

mongooseは、それが実際のMongoDBドライバ(node-mongodb-native)周りのORMのラッパーだ、本当に "ドライバ" ではありません。

あなたがやっていることをするには、ドライバの.find.eachメソッドを見てください。ここでは例からいくつかのコードがあります:

// Find all records. find() returns a cursor 
collection.find(function(err, cursor) { 
    sys.puts("Printing docs from Cursor Each") 
    cursor.each(function(err, doc) { 
    if(doc != null) sys.puts("Doc from Each " + sys.inspect(doc)); 
    })      
}); 

結果をストリーミングするには、基本的に、あなたの「ストリーム」機能とそのsys.putsを交換しています。結果をストリーミングする方法がわからない私はあなたがresponse.write() + response.flush()を行うことができると思うが、あなたはまた、チェックアウトsocket.ioすることがあります。

+1

おかげで持っている - 私は昨日知ったドライバの問題を。私が期待していたfind/cursorソリューションですが、例を見つけるのは驚くほど困難です。ほとんどは見つけてからdocs.foreach(...) –

+0

更新:実際には、私はあなたが記述する方法でこれを動作させることはありませんでした。私がしなければならなかったのは、バックエンドからの応答ストリームとデータストリームを結合するEventEmitterを作成することです。 –

+0

サンプルについては正しいですが、ソースコードの "examples"フォルダが最適です。 'EventEmitter'も正しく聞こえます。あなたが良い例があれば、私たちは間違いなくこの答えをより詳細なもので更新することができます。 –

2

ここで私が見つけた解決策(thatisなら、私にそれを行うには間違った方法を、誰を修正してください)です。 (また悪いコーディングを言い訳 - 遅すぎる私のために今これを飾り立てるために)

var sys = require('sys') 
var http = require("http"); 

var Db = require('/usr/local/src/npm/node_modules/mongodb/lib/mongodb').Db, 
    Connection = require('/usr/local/src/npm/node_modules/mongodb/lib/mongodb').Connection, 
    Collection = require('/usr/local/src/npm/node_modules/mongodb/lib/mongodb').Collection, 
    Server = require('/usr/local/src/npm/node_modules/mongodb/lib/mongodb').Server; 

var db = new Db('test', new Server('localhost',Connection.DEFAULT_PORT , {})); 

var products; 

db.open(function (error, client) { 
    if (error) throw error; 
    products = new Collection(client, 'products'); 
}); 

function ProductReader(collection) { 
     this.collection = collection; 
} 

ProductReader.prototype = new process.EventEmitter(); 

ProductReader.prototype.do = function() { 
     var self = this; 

     this.collection.find(function(err, cursor) { 
       if (err) { 
         self.emit('e1'); 
         return; 

       } 
       sys.puts("Printing docs from Cursor Each"); 

       self.emit('start'); 
       cursor.each(function(err, doc) { 
         if (!err) { 
           self.emit('e2'); 
           self.emit('end'); 
           return; 
         } 

         if(doc != null) { 
           sys.puts("doc:" + doc.name); 
           self.emit('doc',doc); 
         } else { 
           self.emit('end'); 
         } 
       }) 
     }); 
}; 
http.createServer(function(req,res){ 
     pr = new ProductReader(products); 
     pr.on('e1',function(){ 
       sys.puts("E1"); 
       res.writeHead(400,{"Content-Type": "text/plain"}); 
       res.write("e1 occurred\n"); 
       res.end(); 
     }); 
     pr.on('e2',function(){ 
       sys.puts("E2"); 
       res.write("ERROR\n"); 
     }); 

     pr.on('start',function(){ 
       sys.puts("START"); 
       res.writeHead(200,{"Content-Type": "text/plain"}); 
       res.write("<products>\n"); 
     }); 

     pr.on('doc',function(doc){ 
       sys.puts("A DOCUMENT" + doc.name); 
       res.write("<product><name>" + doc.name + "</name></product>\n"); 
     }); 

     pr.on('end',function(){ 
       sys.puts("END"); 
       res.write("</products>"); 
       res.end(); 
     }); 

     pr.do(); 

    }).listen(8000); 
22

node-mongodb-driver(他のすべてのmongoDBクライアントがnodejで使用する下層のレイヤー)は、他の人が触れたカーソルAPIを除いてniceストリームAPI(#458)を持っています。残念ながら、私はそれが他の場所で文書化されているのを見つけられませんでした。

更新:there are docshere

それはこのように使用することができます:

var stream = collection.find().stream() 
stream.on('error', function (err) { 
    console.error(err) 
}) 
stream.on('data', function (doc) { 
    console.log(doc) 
}) 

それが実際にReadableStreamインターフェイスを実装しているので、それはすべてのグッズ(一時停止は/ etc再開)

+1

@Dan Milonがhttp:// mongodbで参照しているものに関するドキュメントが見つかりました。 github.com/ウェブサイトここにそれは[CusrsorStream](http://mongodb.github.com/node-mongodb-native/api-generated/cursorstream.html) – ilikeopensource

+0

これが存在することを知らなかった!ありがとう! [mongodb.github.com/node-mongodb-native] (http://mongodb.github.com/node-mongodb-native)これは問題です。 –

+3

ベスト回答!そしてdocsリンクで! –

関連する問題