本日はそんな方に向けてNode.jsでmongooseを使ったMongoDBの操作法を解説していきます。MongoDBは柔軟性と拡張性に優れNode.js開発者の間で人気を博していますが、MongoDBを効果的に操作するには適切なツールと技術が必要です。その中でもmongooseはMongoDBをNode.jsで操作する際に非常に便利なツールです。mongooseを使えばMongoDBとの対話が簡潔かつ効果的になります。初心者にとってはその使い方を理解することが難しいかもしれません。この記事ではNode.jsでmongooseを使ってMongoDBを操作する方法を解説します。具体的にはSchemaの定義方法から始め、データベースへの接続方法、そしてModelの作成について詳しく説明します。これにより初心者の方々もMongoDBを使ったアプリケーション開発において、自信を持ってスタートできるでしょう。https://youtu.be/Uy05ZhhnLIghttps://youtu.be/G3p44qegvL0MongoDBでデータベースを作るまずMongoDBでアカウントを作成しましょう、Googleログインが便利です。Free」をクリックします。サインアップをします、本記事ではGoogleでサインアップしました。有料と無料で3プランあるので一番右の「M0」という無料プランを選択して「CreateDeployment」という右下の緑ボタンをクリックします。ユーザーの作成を求められますので任意のユーザー名とパスワードを決めて覚えておきます。User」という左下のボタンをクリックします。method」という右下の緑ボタンをクリックします。application」の「Derivers」をクリックします。code」という部分にあるURLをコピーしてエディタなどに貼り付けておきましょう。step」という緑ボタンをクリックします。右下の「Done」という緑ボタンをクリックします。ダッシュボードメニューに戻りますので左メニューの「DEPLOYMENT」の中にある「Database」をクリックします。Collections」というボタンをクリックします。Database」というボタンをクリックしてデータベースを作成します。name」を入力します。本記事ではデータベース名を「sample-db」として、コレクション名を「blogs」とします。以下のように作成したデータベースが左パネルに表示されます。続いてコードの環境構築をしていきます。作業ディレクトリで必要なライブラリをインストールします、すでにインストールされていればスキップして大丈夫です。nodemonserver.jsというファイルを作成してインストールしたライブラリをインポート、インスタンス化します。'ejs');app.listen('3000');ローカルサーバーを立ち上げておきます。nodemonMongoDBはデータベースですので操作するにはSQL文が必要になります。近年のプログラミングではSQLをそのまま実行するのはコードの保全上あまり推奨されておらずAPI経由で操作することがトレンドです。そこでMongoDBではmongooseというライブラリが用意されていて、mongooseを使うことでSQLではなくAPI経由でMongoDBを操作できるようになります。本記事でもmongooseを使用しますのでインストールします。mongoose続いてmongooseをインポートします。require('mongoose');app.listen('3000');APIのURLが必要になり、先ほど保存しておいた以下のURLをコピーしてコードに貼り付けます。='mongodb+srv://admin1234@mongo-basic.hwnaw5l.mongodb.net/?retryWrites=true&w=majority&appName=mongo-basic';app.listen('3000');URLの前段の方にユーザー名とパスワードがあるのが確認できます、これで先ほど開設したデータベースにアクセスできるようになっています。「mongodb+srv://admin1234@mongo-basic.hwnaw5l.mongodb.net/〇〇?retry」の場所にデータベース名も追加します。='mongodb+srv://admin1234@mongo-basic.hwnaw5l.mongodb.net/sample-db?retryWrites=true&w=majority&appName=mongo-basic';app.listen('3000');「sample-db」というデータベース名は先ほどの設定で作った以下のデータベース名のことです。コードを追記していきます。console.log(err));app.listen('3000');API経由でDBに接続するため非同期処理として実行する形になります。mangooseにはconnectというメソッドがあり引数に先ほどのURLを渡すことでMongoDBにアクセスできて、アクセスできた場合にはthenメソッドでアクセスした直後に実行したい処理を書くことができます。上記コードではコンソールログで「DB接続」と表示させていますが、ローカルサーバーを起動できるようにすることが一般的です。以下のようにapp.listen(“3000”)をthenメソッドの処理に移動させましょう。console.log(err));MongoDBの操作結果をNode.jsで画面に表示する方法ここまでは環境構築でしたのでブログサイトを作成しているとして画面にデータを表示させてみます。EJSをインストールしたので以下のように画面を先に作っておきます。</body></html>create.ejsではブログ投稿をしたいと思います。mongooseではモデルという機能を使ってデータをMongoDBに送信して保存させることができます。以下のようにmodelsというフォルダを作成して、その中にblog.jsというファイルを作成します。Blog;mongooseをインポートしておきSchemaというクラスをインスタンス化して、保存したいデータをオブジェクト形式で作成しました。スキーマは保存する型や必須有無など保存設定を書くようなものです。ブログ記事を想定していますのでタイトルをtitleとして本文をcontentとしました。typeは型名のことで文字列にして、requiredは必須有無のことで必須にしました。true}と追加すると記事データが追加された日時も一緒に保存でキアmす。mongooseにあるmodelメソッドをインスタンス化します。引数にドキュメント名で頭文字を大文字にして、第二引数に先ほど作ったスキーマが代入された変数を指定します。引数のドキュメント名はコレクションの単数系に相当するもので、コレクションがデータ群とした場合にドキュメントは1個のデータになっています。前章のデータベース構築でコレクションをblogsとしていたので単数系でBlogがモデルにおけるドキュメント名になる具合です。これでモデルが完成したので最後にBlogという名前でエクスポートしておきました。エクスポートしたのでserver.jsで使用することができます。require('./models/blog');続いてexpressのルーティング設定を作っていきます。{});http://localhost:3000/createにアクセスするとデータを投稿するように/createのルーティングにてモデルBlogをインスタンス化しました。通常の投稿であればユーザーにタイトルと本文を入力してもらうのですが今回は手動でオブジェクトを書きました。/models/blog.jsで作ったBlogをインポートしてインスタンス化し直す時の引数にデータを入れることでMongoDBにデータが送られる仕組みです。上記コードでは定数blogにデータが格納されたので実際に送信するには以下のように追記します。{});mongooseにあるsaveメソッドはデータを保存する非同期処理として動作して、thenメソッドでexpressのsendメソッドを実行しておくことでデータをローカルサーバーに返すようにしました。そのためhttp://localhost:3000/createにアクセスすると送信したデータがブラウザ上に表示されます。続いてトップページであるhttp://localhost:3000にアクセスしたときに保存した内容を一覧にして表示するようにしてみます。{});mongooseのfindメソッドを実行するとMongoDBに保存されているデータを探してくれるようになります。こちらも非同期処理になっていてthenメソッドではexpressのrenderメソッドを使ってindex.ejsにデータを渡すようにしています。index.ejsはすでにデータをループで処理して画面に表示するように作っていました。</body></html>上記コードのblogsにはmongooseのfindメソッドで検索したデータのリストが格納されていることになります。http://localhost:3000にアクセスしてみます。ここでもう一度http://localhost:3000/createにアクセスして同じデータを追加で保存してみます。URLにアクセスするだけで再度データ送信が実行されます。http://localhost:3000に戻ってくるとデータが2件に増えていることが確認できます。確認のためにMongoDBの管理画面も見てみましょう。左メニューから「Database」をクリックします。sample-dbというデータベースのblogsというコレクションをクリックするとデータが2件あります。ブラウザと同じものがMongoDB側にも表示されていることが確認できました。データのプロパティにはtitleとcontentがあるのに加えて_idというものがあります。こちらは自動で追加されるプロパティで投稿を見分けるための識別番号です。一覧にして表示するのではなく個別のデータだけを画面に表示する際に使用します。それではhttp://localhost:3000/aboutで個別のデータを表示させてみます。console.log(err));});mongooseのfindByIdいうメソッドは引数に先ほどの_idの値を文字列にして入れることで対象のデータ1件を取得してくれます。こちらも非同期処理になっていてthenメソッドでは取得した単体のデータをブラウザに返すようにしました。http://localhost:3000/aboutにアクセスしてみます。http://localhost:3000/createの時と同じで作成したデータが再度表示できました。このようにしてmongooseのメソッドを利用してAPI経由でMongoDBを操作することができます。前章ではデータを手書きで書いていましたが実務ではユーザーが操作する場所です。Expressにはユーザーの操作に合わせてMongoDBを操作するメソッドが用意されています。ここでは投稿であるpostメソッド、取得であるgetメソッド、削除であるdeleteメソッドの使い方とmongooseの設定について紹介していきます。Node.jsのExpressでpostメソッドを使ってMongoDBにデータを送信するまずは投稿であるpostメソッドから紹介していきます。mongoDBをmongooseのメソッドを使って連携する部分までは前章と同じになりますので割愛しますが以下のようなコードになります。require('./models/blog');モデルは以下のようになっていて、こちらも前章と同じ内容です。Blog;まず投稿画面はhttps://localhost:3000/createというページにするためにルーティングを書きます。});});続いてcreate.ejsを作ります。</body></html>こちらの画面でタイトルと本文を入力して送信ボタンをクリックしたらMongoDBにデータを送信して、トップページhttp://localhost:3000にリダイレクトするようにします。console.log(req);});画面の表示がapp.getに対して送信はapp.postとして、第一引数には送信後にリダイレクトしたいパス、第二引数にはコールバック関数を書きます。引数のreqにはリクエストオブジェクトが入っており、コンソールでreqを出すと送信したデータを確認できます。postメソッドの直前でミドルウェアでurlencodedというメソッドを実行しておきます。こちらでURLエンコードされたデータを取得してリクエストオブジェクト内に使用可能なオブジェクトを変換します。引数のreqをコンソールで確認できるようにするために書いています。http://localhost:3000/createからデータを送信してみます。コンソールに大量のログがあり最後の方に以下のようになっていてbodyプロパティにデータがあることが確認できます。レスポンスオブジェクトのbodyだけを指定するようにconsole.logを変更します。console.log(req.body);});それではもう一度送ってみましょう。今度はシンプルな構成のオブジェクトでtitleとcontentに作成したデータがあるのが確認できました。こちらのデータをBlogモデルをインスタンス化するときの引数に渡してあげれば良さそうですね。Blog(req.body);});あとはインスタンスメソッドのsaveを使うとMongoDBに送信されます。非同期処理のthenメソッドではexpressのredirectメソッドを使ってトップページに戻るようにしてみます。console.log(err));});MongoDBのコレクションを確認すると前章と同じくデータがオブジェクト形式で格納されているのがわかります。2回やったので同じデータが2件あるのは問題ありません。最後にトップページにリダイレクトするのでExpressのgetメソッドを使ったルーティングと、ejsファイルで投稿データを表示するように作っておきます。以下のコードになりますが前章でやったものと同じ内容です。</body></html>http://localhost:3000に再度アクセスするとデータが表示されています。説明を省略していましたがexpressのgetメソッドは何かしらのデータを取得して画面に表示するときに使用します。前章ではMongDBを使ってなかっただけでブラウザに何かテキストなど表示するには必ずgetメソッドを使っていたはずです。Node.jsのExpressでgetメソッドを使ってMongoDBからデータを取得するそれではデータの一覧はトップページで表示できたので、http://localhost:3000/aboutで1件だけの詳細ページを作ってみます。WordPressのようなCMSツールを使われたことがあればイメージできるかと思いますが1件だけを取得するにはhttp://localhost:3000/idのようにURLの最後が動的なコードになるはずですね。Expressのルーティングでも同じように書きます。console.log(req);});データの表示はgetメソッドで行うのですがデータは引数のreqオブジェクトに格納されております。前章の復習ですが保存したデータはMongoDB側で_idというプロパティでIDが自動生成されます。前章ではID名をコピペして手書きで書いていましたが、実際には_idを指定して動的にIDをリンクする方が好ましいです。index.ejsに戻って投稿データの表示部分にaタグのhref属性を設定しておきましょう。</body></html>これでそれぞれのデータから_idプロパティを指定したことになります。検証ツールを確認するとわかります。それではabout.ejsを作っておきましょう。</body></html>トップページからどれかのデータをクリックしてみます。コンソールでリクエストオブジェクトが長い文章で表示されていてparamsというオブジェクトのidプロパティに_idで見た値が格納されていることがわかります。そのためconsole.log(res.params.id)とすれば_idの値だけ取得できることがわかります。console.log(req.params.id);});一度トップページに戻ってから再度データをクリックしてみましょう。_idだけを取得できましたね。あとはこれを持ってコールバック関数でmongooseのfindByIdメソッドを前章でやったように書くとデータの表示まで作れます。console.log(err));});findByIdメソッドのthenの部分ではabout.ejsを表示するようにしていますので、再度トップページに戻ってからデータをクリックすると以下のように1件だけの表示に切り替わります。Node.jsのExpressでdeleteメソッドを使ってMongoDBからデータを削除する最後にMongoDBに保存されているデータを削除したいと思います。about.ejs側で削除ボタンを作っていたのですが、こちらはformタグの中にあるボタンではないので投稿の時とは違う方法が必要です。formタグが無い以上はブラウザの移動ができません。そのため非同期通信で画面の削除と裏側でMongoDBの中でデータの削除をすることになります。server.jsでExpressのdeleteメソッドを書きます。削除するデータは先ほどの1件取得と同じく_idの値を指定します。console.log(err));});_idの取得方法は先ほどと同じでreq.params.idとしているのと、削除するにはmongooseのfindByIdAndDeleteというメソッドの引数に_idを入れます。こちらのthenメソッドではトップページにリダイレクトするようにしています。今のままだとブラウザ側では画面移動はしないためレスポンスでリダイレクト先のパスが返ってくるだけで、画面は削除されたはずのabout.ejsが表示され続けることになります。そこでabout.ejsではserver.jsで返されたリダイレクト先のパスをもらってフロントでの画面移動を行います。</body></html>1件取得でやったように今いるページの_idを知りたいのでbuttonタグにdata属性を使って設定するように変更しました。data属性に置いていた_idの値を使ってfetchメソッドを実行してwindow.loacation.hrefで画面移動をしています。削除は別ページを作ってそこではformタグを設置して投稿と同じような流れで削除することも可能ですが、今回は簡易的にabout.ejsの中で削除ボタンを設置したので上記コードのようになりました。いえ近年のプログラミングではフロントエンドでの画面移動も当たり前になりましたので上記のような使い方は初心者の方も練習しておくと良いかもしれません。それでは削除ボタンをクリックしてみます。前章で2件のデータを作成したので1件だけになっているはずです。MongoDBも確認してみると画面と同じく1件だけのデータになっていますね。前章までで基本的なデータベースの操作方法を紹介してきましたがserver.jsの中身がやや長くなってきました。リファクタリングの意味もこめてMVCモデルを紹介しておきます。routesというフォルダを作成し、その中にroutes.jsというファイルを作成しておきます。routes.js-server.jsExpressにはRouterというクラスがインスタンス化することで現在のプロジェクトまでのルートパスを取得してくれます。それによって今までserver.jsで書いていた関数を/routes/routes.jsに切り出すことができます。router;またコードの最後にmodules.exportsを使ってエクスポートしておき、関数を取り除いたserver.js側でインポートして/routes/routes.jsから関数を読み込むようにします。関数を読み込む方法ですがuseメソッドを使ったミドルウェアとして読み込ます形になります。ミドルウェアという仕組みを使うことでリクエストとレスポンスの間で関数を呼び出すことになり、結果的にもともとserver.jsに関数を書いていたのと同じ動作を実現できるわけです。ここを追加app.use(router);これでserver.js側は綺麗になりましたが/routes/routes.jsの中身が結局は見づらい状況になっただけです。そこでExpressのControllerというクラスを使って関数を名前付きの変数に書き直して、名前として呼び出すことができるようになります。以下のようにcontrollersというフォルダを作って、その中にcontroller.jsというファイルを作成します。controller.js-server.js/controllers/controller.jsの中ではまずControllerというクラスをインスタンス化しておきます。続いて/routes/routes.jsに切り出した関数をアロー関数の形に作って変数に格納する書き方にします。blogDelete,};最後に作った変数化したアロー関数をエクスポートして/routes/routes.jsでインポートするようにしておきます。router;/routes/routes.jsの中身でgetメソッド、postメソッド、deleteメソッド共に第一引数は実行するパス名、第二引数が関数が格納された変数名だけを書く方法に変わります。最終的にserver.jsにエクスポートするので、controller.js→routes.js→server.jsと中継しながら処理の内容が渡されserver.js内のミドルウェアとしてリクエストとレスポンスの間で読み込まれ実行されます。最後にdotenvというミドルウェアのライブラリを紹介します。インストールしてインポートしておき、configというメソッドを実行しておきます。ここを追加app.use(router);JavaScriptのプロジェクトでは「.env」というファイルを作るとソースコード上でAPIキーやURL、パスワードなど大事な情報を非表示にして書くことができるようになります。上記のコードで言うところの定数dbUrlとapp.listenのポート番号になります。こちらをまず「.env」ファイルに逃しておきましょう。"mongodb+srv://admin:ttc19930104@mongo-basic.hwnaw5l.mongodb.net/mongo-db?retryWrites=true&w=majority&appName=mongo-basic"隠したい値は変数のように特定のキーワードで差し替える形になるので、上記コードのようにPORTとMONGO_DBというキーワードに代入しておきます。続いてserver.jsに戻ってキーワードに差し替えますが、proccess.envと続けることで「.env」の中で書いたキーワードから候補を探してくれるようになります。console.log(err));定数dbUrlについてはMONGO_DBというキーワードに代入しておいたのでprocess.env.MONGO_DBとして、app.listenのポート番号についてはPORTというキーワードに代入しておいたのでprocess.env.PORTと書きます。これでソースコードに値を表示させずに動作を行うことができます。Githubにあげるときには.envを.gitignoreというファイルの中に書きます。.envに逃しても結局Githubに上げてしまったら確認できてしまいます。そこで.gitignoreという特殊なファイルを作成すると、その中に書いたファイルはGitでプッシュされないことになります。controller.js-server.js-.env-.gitignore.envユーザーから見たら違いはわかりませんがプロジェクトを安全に共有する上では必須の知識になり、チーム開発では登場する言葉なので初心者の方も理解しておくようにしてください。Node.jsでMongoDBにハッシュ化したパスワードを保存するセキュリティ対策の別の例としてパスワードのハッシュ化というものも紹介します。ユーザー情報を保存するときにパスワードをMongoDBに保存するわけですが、実際にはパスワードをそのまま保存するのはあまり好ましくないです。MongoDBの管理画面を覗かれたときに備えてユーザーのパスワードはダミーのテキストに変換しておくのが実務でよくやるパターンです。専門用語でハッシュ化とも呼ばれていてNode.jsではbcryptというライブラリを使うと簡単に実装できます。bcryptはサードパーティ製のライブラリですのでインストールしておきます。bcrypt続いてユーザー登録のモデルを作成します。usernameがユーザー名でpasswordがパスワードになり2項目をユーザー情報として保存する想定で作りました。userModel;コントローラーでモデルとbcryptをインポートします。bcryptはgenSaltというメソッドでハッシュ化したいパスワードの文字数を指定します。以下の例では8桁にしています。hashというメソッドがあり第一引数にパスワードが格納された変数、第二引数にgenSaltの戻り値を格納した変数を入れます。するとhashメソッドの戻り値にダミーテキストに変換されたパスワードが保存される仕組みです。あとはモデル側でパスワードをpasswordという項目で用意していましたが、ハッシュ化されたhashedPassに置き換えておけばOKです。};例えば「test1234」というパスワードを送信しても以下のような形で保存されます。今回参考にした書籍はこちらになりますので良ければどうぞ。