質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
MongoDB

MongoDBはオープンソースのドキュメント指向データベースの1つです。高性能で、多くのリトルエンディアンシステムを利用することができます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Q&A

2回答

1715閲覧

Node.js(Express) + MongoDBで全件検索したときのクライアントの閉じ方がわからない。

pyon_214

総合スコア8

MongoDB

MongoDBはオープンソースのドキュメント指向データベースの1つです。高性能で、多くのリトルエンディアンシステムを利用することができます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

0グッド

0クリップ

投稿2020/10/07 12:25

Node.js(Express)とMongoDBで全件検索をしたときのクライアントの閉じ方がわかりません。

route.js

1router.get("/*", (req,res)=>{ 2 MongoClient.connect(CONNECTION_URL, OPTIONS, (error, client)=>{ 3 var db = client.db(DATABASE); 4 db.collection("cars").find({}) 5 .toArray((error, docs)=>{ 6 if(error){ 7 res.status(500); 8 client.close(); 9 }else{ 10 console.log(docs); 11 res.render("./show/index.ejs", {docs}); 12 client.close(); 13 }}); 14 }); 15});

本当はif(error){client.close()}else{client.close()}と別々に記述するのではなく、最後に.then(()=>{client.close()})と記述したいのですが、エラーが発生します。

当方初学者のため、とんちんかんなことをしてしまっているかもしれませんが、よろしければ有識者の皆様からお知恵を貸していただけると大変助かります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

そもそもの所でNode.jsの強みが消えますので
コネクションは基本的に閉じずに運用してください。

というわけでコネクションを閉じない運用の提案をしていきます。
MongoDBにはコネクションプールという機能が存在します
参考サイト: 公式サイトドキュメント#コネクションプール

MongoClient connection pooling

A Connection Pool is a cache of database connections maintained by the driver so that connections can be re-used when new connections to the database are required. To reduce the number of connection pools created by your application, we recommend calling MongoClient.connect once and reusing the database variable returned by the callback:

和訳

MongoClient コネクションプール
コネクションプールとは、ドライバが管理するデータベース接続のキャッシュのことで、 データベースへの新しい接続が必要になったときに接続を再利用できるようにします。アプリケーションが作成するコネクションプールの数を減らすには、 MongoClient.connect を一度コールしてコールバックで返されたデータベース変数を再利用することをお勧めします。

解説しますと、Webサーバは同時に何百人というユーザがWebサービスを利用しようと訪れる可能性があります。
その何百人が一斉にrouter.get("/*", fn)に押し寄せたとすると、
MongooDBサーバにその何百人分のコネクションよこせが来るので最初の3人だけ受け付けて、残り数百人はエラーという結果になりかねません。
(MongoDBというアプリもそこまでヤワな作りでは無いでしょうし、実際にはそれなりに上手くやるでしょうけどね)

その対策としてコネクションプールという機能が存在します。
プールは学校とかにある水が張っていて泳げるプールを指します。
水面にビート板のように接続状態のコネクションを投げ入れておき、利用者が取れるような仕組みになっています。
(MySQL等の他のデータベースにもある、わりとよくある作戦です)

コネクションプールを使いNode.jsとMongoDBを接続させますと、
予め3本の接続を予約しておいてすぐ使える状態にします。
(この時の接続本数は設定により自由に変更が可能です)

100人のユーザーが訪れた場合、最初の3人に接続を使わせておき
残り97人には「ちょっと待ってろ」と待たせます。
3本の問い合わせは、問い合わせ完了後、コネクションプールに接続を返しに来ます。

接続がコネクションプールに帰ってきたら4人目、5人目という風に
順番待ちしている人たちに接続を使わせるという仕組みになります。

コードに関してはドキュメントの下にあります
軽くコメントで注釈入れつつ、一緒に見ていきましょう。

js

1var express = require('express'); 2var mongodb = require('mongodb'); 3var app = express(); 4 5var MongoClient = require('mongodb').MongoClient; 6// 予めコネクションプール用の変数を宣言しておく 7var db; 8 9// 初期処理としてMongoDBのコネクションを確保する 10MongoClient.connect("mongodb://localhost:27017/integration_test", function(err, database) { 11 if(err) throw err; 12 13 // MongoDBとの接続が完了したらコネクションプール用の変数へ代入 14 db = database; 15 16 // MongoDBとの接続が完了してからExpress.jsを立ち上げるのだ 17 app.listen(3000); 18 console.log("Listening on port 3000"); 19}); 20 21// 改めてExpress.jsの設定を記述していく 22app.get("/", function(req, res) { 23 // コネクションプール利用時の書き方は特に変わらない 24 // こうするだけで勝手に順番待ちを作って解決してくれる 25 db.collection("replicaset_mongo_client_collection").find({}, function(err, docs) { 26 docs.each(function(err, doc) { 27 if(doc) { 28 console.log(doc); 29 } 30 else { 31 // コネクションを閉じる記述の必要無し 32 res.end(); 33 } 34 }); 35 }); 36});

投稿2020/10/08 04:38

編集2020/10/08 04:42
miyabi-sun

総合スコア21203

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

私の場合、こんな感じでコーディングしたりします。
よろしかったら参考にしてください。

Javascript

1router.get("/*", (req, res) => { 2 3 let query = {..........}; 4 5 MongoClient.connect(CONNECTION_URL, OPTIONS, (error, client) => { 6 let db = client.db(DATABSE); 7 8 Promise.all([ 9 db.collection(..........) 10 .find(query) 11 .......... 12 .toArray() 13 ]).then((results) => { 14 let data = { 15 .......... 16 } 17 }; 18 res.render("index.ejs", data); 19 }).catch((error) => { 20 throw error; 21 }).then(() => { 22 client.close(); 23 }); 24 }); 25}); 26 27module.exports = router;

投稿2020/10/07 12:56

technocore

総合スコア7337

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問