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

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

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

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

Node.js

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

Q&A

解決済

2回答

2722閲覧

NodeとMongoDBの接続をしたい

Libra189

総合スコア8

MongoDB

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

Node.js

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

0グッド

0クリップ

投稿2017/08/04 01:50

###前提・実現したいこと
JavaScript初学者です。よろしくお願いします。
Node.js(Express)でMongoDBとの接続をしたいと考えております。
このサイトを参考に共通処理(MongoDB関連処理)を作成しました(「共通処理を作る」を参考)。
下記コードを実装しましたが、想定通りに動かず困っています。
調べ方もわからずどうしていいかわかりません。よろしくお願いします。

###該当のソースコード

javascript

1// lib/db.js 2var assert = require('assert'); 3var mongodb = require('mongodb'); 4var MongoClient = mongodb.MongoClient; 5 6module.exports = { 7 connection: null, // 関数connect実行後もnull 8 9 connect: function() { 10 MongoClient.connect(config.mongodb.url, function (err, db) { 11 assert.equal(null, err); 12 this.connection = db; 13 console.log(this.connection); // プロパティが色々表示 14 }); 15 console.log(this.connection); // null 16 console.log('Database Connect'); 17 }, 18};

javascript

1// index.js 2var mongo = require('./lib/db'); 3mongo.connect(); 4console.log(mongo); // { connection: null, connect: [Function: connect] }

###発生している問題・エラーメッセージ
lib/db.jsで定義したconnect関数をindex.jsで実行してもプロパティconnectionがnullから変わりません。想定している動作はindex.jsでconnect関数を実行するとmongoDBのコネクションがプロパティconnectionに格納されていることです。

###試したこと
コールバック関数内にreturn文を入れたり、コールバック関数をそもそも使わなかったりしましたが、想定通りに動いてくれませんでした。
コールバック関数を使用しない場合はプロパティconnectionがPendingとなり動きが中身が変わっていました。

###補足情(言語/FW/ツール等のバージョンなど)
nodejs:v8.2.1
mongodb:2.2.30

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

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

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

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

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

guest

回答2

0

ベストアンサー

Node.jsはシングルスレッドで動作しており、
そのほとんどのAPIが非同期イベント駆動での動作を想定しています。
DB操作といったライブラリを扱うには、最低限の非同期プログラミングへの理解が必要です。

もしnode.jsでDB操作やファイル操作等を同期処理で動かしたならば、
使い物にならないプロダクトが量産され、ここまで普及することはまずあり得ません。

質問者さんのデバッグコードの書き方(差し込み方)からして、
同期プログラミングの考え型で「動かない」とおっしゃっているようです。

Javascriptでコールバックによる非同期処理を書いた場合、
上から順番にコードが実行されるわけではありませんのでご注意ください。

今回のコードでしたら、だいたいのイメージとしまして、
コールバック関数以外のコードが上から順番に実行されます。

Javascript

1// lib/db.js 2var assert = require('assert');//まずこれ読む 3var mongodb = require('mongodb');//次これ読み込まれる 4var MongoClient = mongodb.MongoClient;//その次これ読み込まれる 5 6//ここまで順番どうりです。 7//↓もconnectionの初期化(null代入)とconnect関数を定義し、外部公開が完了。 8module.exports = { 9 connection: null, 10 //connect関数定義 11 connect: function() { 12 MongoClient.connect(config.mongodb.url); //繋いでという命令実行。繋がったら登録したコールバック関数を後で実行してね、という約束だけはした。 13 console.log(this.connection);// まだ繋がってないのでnullで初期化されたnullが表示されます。 14 console.log('Database Connect');//Database Connectが出力 15 16 //この関数をぬけると呼び出していたindex.jsの続きが実行されます。 17 }, 18}; 19

Javascript

1// index.js 2var mongo = require('./lib/db'); //上記クラスを読み込み(lib/db.jsが走ります) 3mongo.connect(); //上に記載したconnect関数のコメントの挙動となります。要するに「繋がったら教えて」と頼んだだけです。 4console.log(mongo); // 頼んですぐデバッグ表示させたので、期待したものは得られてません。 5//ここでメインプログラム(index.js)終了。

index.jsは終了しましたが、続きがあります。
MongoClientにコールバックを登録していたので、プロセスは死んでません。
MongoClientから接続処理の結果としてコールバック関数が、このタイミングで呼び出されます。
DBの接続は速そうに見えても、プログラム的には色々と手続き処理があり、そこそこ重い処理となるので、今回のコード内容ですと、タイミング的にはindex.jsの同期処理の後となる、このタイミングになるはずです。

Javascript

1//MongoClientに登録されたコールバックが実行。クロージャによりthisが元気に問題なく動きます。 2assert.equal(null, err); 3this.connection = db; //mongo.connectionにdb接続オブジェクト代入 4console.log(this.connection); // db接続オブジェクト表示 5//コールバック処理が終わったので、プロセスがここでやっと死にます。

というような挙動となります。
え!これだと全部コールバックの中に処理を書かなくちゃいけないじゃん!
となると思うのですが、その通りです。
これがJavascriptのコールバック地獄というものでして、どんどんこれが続いていきます。

多くのWeb系エンジニアが長らく苦労してきた地獄なのですが、
当然打開策がありまして、まずはPromiseパターンの導入。
これでコールバック地獄から一気に抜け出せます。

そして次にco&generatorまたはasync/await構文を採用すれば、
同期処理のノリで非同期処理が書けます。
これらの情報は上質な記事が豊富にありますので、
非同期プログラミングへの理解が進めば、答えがでてくるかと思います。

投稿2017/08/07 04:34

編集2017/08/07 04:53
so87

総合スコア764

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

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

Libra189

2017/08/07 09:44

丁寧な回答ありがとうございます。 非同期通信やJavaScriptの処理順について詳しく知ることができました。 教えていただいたことをヒントに処理を組んでみます
anndonut

2017/08/07 11:18

PromiseパターンはNode.js v0.12以降からなので、Aizu Online Judgeでは使えないんですね。残念。 でもso87さんの情報、非常に参考になります。自分は、ドライバーモジュールと同じインターフェースを 持たせるくらいの解しかもっていなかったので。 あとLibra189さんの意図も組めなくて申し訳なかったです。
guest

0

Node.js自体は知っていますが、Node.jsでデータベースを操作した経験はありません。
私も試行錯誤すれば正しい回答をできると思うのですが、まず、私ならこうするというのを
書いておきます。

  1. データベースに慣れる

データベースサーバは、コマンドラインから操作することができます。
tutorialspointなどが参考になると思います。
tutorialspoint MongoDB - Environment

MySQLのほうがメジャーで、日本語の解説も多いので個人的にはMySQLをお勧めしますが、
ともかく、手打ちでデータベースを一通り操作できるようになることです。

  1. データベースに接続する

Node.jsでmongoDBに接続するためには、Node.jsを実行する前にmongoDBサーバを
立ち上げておく必要があります。Node.jsのmongodbモジュールはあくまでmongoDBを
操作するためのドライバーであって、mongoDBそのものではないです。
GitHubのREADME.mdにはその簡単な手順が書いてあるようです。
GitHub - Mongo DB Native NodeJS Driver

頑張ってください。
以上

投稿2017/08/04 12:20

anndonut

総合スコア667

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

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

Libra189

2017/08/07 01:37

ご回答、アドバンス阿知賀等ございます。 MongoDBについては基本的な操作、接続の工程は完了しています。 1ファイルで接続、操作、切断はできるのですが、モジュールに分けるとできなくなりました。 JSについても初学者のため問題の原因を特定することができませんでした。 モジュールに分けた際のクラスの注意事項などあれば教えてくいただきたく思います。 よろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問