Nodejsとexpressを使用して、JSONを使用して1つまたは複数のオブジェクト(配列)を返します。以下のコードでは、一度に1つのJSONオブジェクトを出力します。それは動作しますが、これは私が望むものとはまったく異なります。私が多くのオブジェクトを持っているので、生成された応答は有効なJSON応答ではありません。
すべてのオブジェクトを単純に配列に追加し、res.endでその特定の配列を返すことができることをよく知っています。ただし、これは処理が重くなり、メモリを大量に消費する可能性があります。
Nodejsでこれを達成する適切な方法は何ですか? query.eachは呼び出すのに適切なメソッドですか?
app.get('/users/:email/messages/unread', function(req, res, next) {
var query = MessageInfo
.find({ $and: [ { 'email': req.params.email }, { 'hasBeenRead': false } ] });
res.writeHead(200, { 'Content-Type': 'application/json' });
query.each(function(err, msg) {
if (msg) {
res.write(JSON.stringify({ msgId: msg.fileName }));
} else {
res.end();
}
});
});
これが本当に違うかどうかはわかりませんが、クエリカーソルを反復処理するのではなく、次のようなことができます。
query.exec(function (err, results){
if (err) res.writeHead(500, err.message)
else if (!results.length) res.writeHead(404);
else {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.write(JSON.stringify(results.map(function (msg){ return {msgId: msg.fileName}; })));
}
res.end();
});
[編集]Mongooseのドキュメントを確認した後、各クエリ結果を個別のチャンクとして送信できるようです。 Webサーバーは チャンク転送エンコーディングデフォルト を使用するため、必要なことは、アイテムを有効なJSONオブジェクトにするために配列をラップするだけです。
大まかに(未テスト):
app.get('/users/:email/messages/unread', function(req, res, next) {
var firstItem=true, query=MessageInfo.find(/*...*/);
res.writeHead(200, {'Content-Type': 'application/json'});
query.each(function(docs) {
// Start the JSON array or separate the next element.
res.write(firstItem ? (firstItem=false,'[') : ',');
res.write(JSON.stringify({ msgId: msg.fileName }));
});
res.end(']'); // End the JSON array and response.
});
または、言及したように、単に配列の内容をそのまま送信することもできます。この場合、 応答本文はバッファリングされます すぐに送信され、大きな結果セットに対して(結果を保存するために必要な量を超える)追加のメモリを大量に消費する可能性があります。例えば:
// ...
var query = MessageInfo.find(/*...*/);
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(query.map(function(x){ return x.fileName })));