MongoDBをノードアプリケーションと統合する方法

前書き

Node.jsを使用していると、データを格納および照会するプロジェクトを開発していることに気付く場合があります。 この場合、アプリケーションのデータとクエリの種類に合ったデータベースソリューションを選択する必要があります。

このチュートリアルでは、MongoDBデータベースを既存のノードアプリケーションと統合します。 MongoDBのようなNoSQL databasesは、データ要件にスケーラビリティと柔軟性が含まれている場合に役立ちます。 MongoDBは、JSONオブジェクトと非同期で動作するように設計されているため、Nodeともうまく統合できます。

MongoDBをプロジェクトに統合するには、Object Document Mapper(ODM)Mongooseを使用して、アプリケーションデータのスキーマとモデルを作成します。 これにより、model-view-controller (MVC)アーキテクチャパターンに従ってアプリケーションコードを整理できます。これにより、アプリケーションがユーザー入力を処理する方法のロジックを、データが構造化されてユーザーにレンダリングされる方法から分離できます。 このパターンを使用すると、懸念事項の分離をコードベースに導入することで、将来のテストと開発を促進できます。

チュートリアルの最後に、お気に入りのサメに関するユーザーの入力を受け取り、結果をブラウザに表示する、機能するサメ情報アプリケーションがあります。

Shark Output

前提条件

[[step-1 -—- creating-a-mongo-user]] ==ステップ1—Mongoユーザーの作成

アプリケーションコードの操作を開始する前に、アプリケーションのデータベースにアクセスできる管理ユーザーを作成します。 このユーザーには、任意のデータベースに対する管理者権限があります。これにより、必要に応じて新しいデータベースを切り替えて作成する柔軟性が得られます。

まず、サーバーでMongoDBが実行されていることを確認します。

sudo systemctl status mongodb

次の出力は、MongoDBが実行されていることを示しています。

Output● mongodb.service - An object/document-oriented database
   Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2019-01-31 21:07:25 UTC; 21min ago
...

次に、Mongoシェルを開いてユーザーを作成します。

mongo

これにより、管理シェルに移動します。

OutputMongoDB shell version v3.6.3
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.6.3
...
>

adminデータベースへの無制限のアクセスが原因で、シェルを開くと、いくつかの管理上の警告が表示されます。 このアクセスを制限する方法について詳しくは、本番環境に移行するときのHow To Install and Secure MongoDB on Ubuntu 16.04を参照してください。

今のところ、adminデータベースへのアクセスを使用して、userAdminAnyDatabase権限を持つユーザーを作成できます。これにより、アプリケーションのデータベースへのパスワードで保護されたアクセスが可能になります。

シェルで、adminデータベースを使用してユーザーを作成することを指定します。

use admin

次に、db.createUserコマンドでユーザー名とパスワードを追加して、役割とパスワードを作成します。 このコマンドを入力すると、シェルはコマンドが完了するまで各行の前に3つのドットを付加します。 ここで提供されるユーザーとパスワードを、必ず自分のユーザー名とパスワードに置き換えてください。

db.createUser(
  {
    user: "sammy",
    pwd: "your_password",
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  }
)

これにより、adminデータベースにユーザーsammyのエントリが作成されます。 選択したユーザー名とadminデータベースは、ユーザーの識別子として機能します。

エントリが成功したことを示すメッセージを含む、プロセス全体の出力は次のようになります。

Output> db.createUser(
...  {
...    user: "sammy",
...    pwd: "your_password",
...    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
...  }
...)
Successfully added user: {
        "user" : "sammy",
        "roles" : [
                {
                        "role" : "userAdminAnyDatabase",
                        "db" : "admin"
                }
        ]
}

ユーザーとパスワードを作成したら、Mongoシェルを終了できます。

exit

データベースユーザーを作成したので、次に、スタータープロジェクトコードのクローン作成とMongooseライブラリの追加に進むことができます。これにより、データベースのコレクションのスキーマとモデルを実装できます。

[[step-2 -—- adding-mongoose-and-database-information-to-the-project]] ==ステップ2—マングースとデータベースの情報をプロジェクトに追加する

次の手順では、アプリケーションのスターターコードを複製し、MongooseとMongoDBデータベース情報をプロジェクトに追加します。

root以外のユーザーのホームディレクトリで、DigitalOcean Community GitHub accountからnodejs-image-demo repositoryのクローンを作成します。 このリポジトリには、How To Build a Node.js Application with Dockerで説明されているセットアップのコードが含まれています。

リポジトリをnode_projectというディレクトリに複製します。

git clone https://github.com/do-community/nodejs-image-demo.git node_project

node_projectディレクトリに移動します。

cd  node_project

プロジェクトコードを変更する前に、treeコマンドを使用してプロジェクトの構造を見てみましょう。

[。注意]##

Tip:treeは、コマンドラインからファイルとディレクトリの構造を表示するための便利なコマンドです。 次のコマンドでインストールできます:

sudo apt install tree

これを使用するには、cdを特定のディレクトリに挿入し、treeと入力します。 次のようなコマンドを使用して、開始点へのパスを指定することもできます。

tree /home/sammy/sammys-project

次のように入力して、node_projectディレクトリを確認します。

tree

現在のプロジェクトの構造は次のようになります。

Output├── Dockerfile
├── README.md
├── app.js
├── package-lock.json
├── package.json
└── views
    ├── css
    │   └── styles.css
    ├── index.html
    └── sharks.html

チュートリアルを進めながら、このプロジェクトにディレクトリを追加します。treeは、進行状況を追跡するのに役立つコマンドです。

次に、npm installコマンドを使用して、mongoosenpmパッケージをプロジェクトに追加します。

npm install mongoose

このコマンドは、プロジェクトのpackage.jsonファイルにリストされている依存関係を使用して、プロジェクトディレクトリにnode_modulesディレクトリを作成し、そのディレクトリにmongooseを追加します。 また、package.jsonファイルにリストされている依存関係にmongooseを追加します。 package.jsonの詳細については、How To Build a Node.js Application with DockerStep 1を参照してください。

Mongooseのスキーマまたはモデルを作成する前に、データベース接続情報を追加して、アプリケーションがデータベースに接続できるようにします。

アプリケーションの懸念事項を可能な限り分離するために、データベース接続情報用にdb.jsという別のファイルを作成します。 このファイルは、nanoまたはお気に入りのエディターで開くことができます。

nano db.js

まず、require関数を使用してmongoosemoduleをインポートします。

~/node_project/db.js

const mongoose = require('mongoose');

これにより、データベースへの接続を作成するために使用するMongooseの組み込みメソッドにアクセスできます。

次に、次のconstantsを追加して、Mongoの接続URIの情報を定義します。 ユーザー名とパスワードはオプションですが、データベースに認証を要求できるようにそれらを含めます。 以下にリストされているユーザー名とパスワードを自分の情報に置き換えてください。必要に応じて、データベースを'sharkinfo'以外の名前で自由に呼び出してください。

~/node_project/db.js

const mongoose = require('mongoose');

const MONGO_USERNAME = 'sammy';
const MONGO_PASSWORD = 'your_password';
const MONGO_HOSTNAME = '127.0.0.1';
const MONGO_PORT = '27017';
const MONGO_DB = 'sharkinfo';

データベースをローカルで実行しているため、ホスト名として127.0.0.1を使用しました。 これは、他の開発コンテキストで変更されます。たとえば、別のデータベースサーバーを使用している場合や、コンテナ化されたワークフローで複数のノードを操作している場合です。

最後に、URIの定数を定義し、mongoose.connect()メソッドを使用して接続を作成します。

~/node_project/db.js

...
const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;

mongoose.connect(url, {useNewUrlParser: true});

URIで、ユーザーのauthSourceadminデータベースとして指定していることに注意してください。 接続文字列でユーザー名を指定したため、これが必要です。 useNewUrlParserフラグをmongoose.connect()とともに使用すると、Mongoのnew URL parserを使用することを指定します。

編集が終了したら、ファイルを保存して閉じます。

最後のステップとして、データベース接続情報をapp.jsファイルに追加して、アプリケーションがそれを使用できるようにします。 app.jsを開きます:

nano app.js

ファイルの最初の行は次のようになります。

~/node_project/app.js

const express = require('express');
const app = express();
const router = express.Router();

const path = __dirname + '/views/';
...

ファイルの先頭近くにあるrouter定数定義の下に、次の行を追加します。

~/node_project/app.js

...
const router = express.Router();
const db = require('./db');

const path = __dirname + '/views/';
...

これは、db.jsで指定されたデータベース接続情報を使用するようにアプリケーションに指示します。

編集が終了したら、ファイルを保存して閉じます。

データベース情報を配置し、Mongooseをプロジェクトに追加すると、sharksコレクションのデータを形成するスキーマとモデルを作成する準備が整います。

[[step-3 -—- creating-mongoose-schemas-and-models]] ==ステップ3—Mongooseスキーマとモデルの作成

次のステップは、ユーザーが入力を使用してsharkinfoデータベースに作成するsharksコレクションの構造について考えることです。 これらの作成されたドキュメントにどのような構造を持たせたいですか? 現在のアプリケーションのサメ情報ページには、さまざまなサメとその行動に関する詳細が含まれています。

Shark Info Page

このテーマに沿って、ユーザーにキャラクター全体の詳細を含む新しいサメを追加してもらうことができます。 この目標により、スキーマの作成方法が決まります。

スキーマとモデルをアプリケーションの他の部分と区別するために、現在のプロジェクトディレクトリにmodelsディレクトリを作成します。

mkdir models

次に、sharks.jsというファイルを開いて、スキーマとモデルを作成します。

nano models/sharks.js

ファイルの先頭にあるmongooseモジュールをインポートします。

~/node_project/models/sharks.js

const mongoose = require('mongoose');

この下に、sharkスキーマの基礎として使用するSchemaオブジェクトを定義します。

~/node_project/models/sharks.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

これで、スキーマに含めるフィールドを定義できます。 個々のサメとその行動に関する情報を含むコレクションを作成したいので、namekeyキーとcharacterキーを含めましょう。 定数定義の下に次のSharkスキーマを追加します。

~/node_project/models/sharks.js

...
const Shark = new Schema ({
        name: { type: String, required: true },
        character: { type: String, required: true },
});

この定義には、ユーザーに期待する入力のタイプ(この場合はstring)と、その入力が必要かどうかに関する情報が含まれています。

最後に、Mongooseのmodel() functionを使用してSharkモデルを作成します。 このモデルを使用すると、コレクションからドキュメントを照会し、新しいドキュメントを検証できます。 ファイルの下部に次の行を追加します。

~/node_project/models/sharks.js

...
module.exports = mongoose.model('Shark', Shark)

この最後の行は、module.exports propertyを使用するモジュールとしてSharkモデルを使用できるようにします。 このプロパティは、モジュールがエクスポートする値を定義し、アプリケーションの他の場所で使用できるようにします。

完成したmodels/sharks.jsファイルは次のようになります。

~/node_project/models/sharks.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const Shark = new Schema ({
        name: { type: String, required: true },
        character: { type: String, required: true },
});

module.exports = mongoose.model('Shark', Shark)

編集が終了したら、ファイルを保存して閉じます。

Sharkスキーマとモデルを配置したら、アプリケーションがユーザー入力を処理する方法を決定するロジックの作業を開始できます。

[[step-4 -—- creating-controllers]] ==ステップ4—コントローラーの作成

次のステップでは、ユーザー入力がデータベースに保存され、ユーザーに返される方法を決定するコントローラーコンポーネントを作成します。

まず、コントローラーのディレクトリを作成します。

mkdir controllers

次に、そのフォルダー内のsharks.jsというファイルを開きます。

nano controllers/sharks.js

ファイルの先頭で、Sharkモデルを使用してモジュールをインポートし、コントローラーのロジックで使用できるようにします。 また、path moduleをインポートしてユーティリティにアクセスし、ユーザーがサメを入力するフォームへのパスを設定できるようにします。

次のrequire関数をファイルの先頭に追加します。

~/node_project/controllers/sharks.js

const path = require('path');
const Shark = require('../models/sharks');

次に、ノードのexports shortcutを使用して、コントローラーモジュールでエクスポートする一連の関数を記述します。 これらの機能には、ユーザーのサメデータに関連する3つのタスクが含まれます。

  • ユーザーにサメの入力フォームを送信します。

  • 新しいサメのエントリを作成します。

  • サメをユーザーに表示します。

まず、index関数を作成して、入力フォームを含むサメのページを表示します。 この関数をインポートの下に追加します。

~/node_project/controllers/sharks.js

...
exports.index = function (req, res) {
    res.sendFile(path.resolve('views/sharks.html'));
};

次に、index関数の下に、createという関数を追加して、sharksコレクションに新しいサメのエントリを作成します。

~/node_project/controllers/sharks.js

...
exports.create = function (req, res) {
    var newShark = new Shark(req.body);
    console.log(req.body);
    newShark.save(function (err) {
            if(err) {
            res.status(400).send('Unable to save shark to database');
        } else {
            res.redirect('/sharks/getshark');
        }
  });
               };

この関数は、ユーザーがサメのデータをsharks.htmlページのフォームに投稿したときに呼び出されます。 チュートリアルの後半でアプリケーションのルートを作成するときに、このPOSTエンドポイントを使用してルートを作成します。 POSTリクエストのbodyを使用して、create関数は、インポートしたSharkモデルを使用して、ここではnewSharkと呼ばれる新しいsharkドキュメントオブジェクトを作成します。 POSTメソッドが意図したとおりに機能していることを確認するために、コンソールにsharkエントリを出力するconsole.log methodを追加しましたが、必要に応じてこれを省略してください。

次に、newSharkオブジェクトを使用して、create関数はMongooseのmodel.save() methodを呼び出し、Sharkモデルで定義したキーを使用して新しいサメドキュメントを作成します。 このcallback functionは、standard Node callback patternの後に続きます:callback(error, results)。 エラーの場合は、エラーを報告するメッセージをユーザーに送信します。成功した場合は、res.redirect() methodを使用してユーザーをエンドポイントに送信し、サメの情報をユーザーに返します。ブラウザで。

最後に、list関数は、コレクションのコンテンツをユーザーに表示します。 create関数の下に次のコードを追加します。

~/node_project/controllers/sharks.js

...
exports.list = function (req, res) {
        Shark.find({}).exec(function (err, sharks) {
                if (err) {
                        return res.send(500, err);
                }
                res.render('getshark', {
                        sharks: sharks
             });
        });
};

この関数は、Sharkモデルとマングースのmodel.find() methodを使用して、sharksコレクションに入力されたサメを返します。 これは、Mongooseのexec() functionを使用して、クエリオブジェクト(この場合はsharksコレクション内のすべてのエントリ)をpromiseとして返すことによって行われます。 エラーの場合、コールバック関数は500エラーを送信します。

sharksコレクションで返されたクエリオブジェクトは、EJSテンプレート言語を使用して次のステップで作成するgetsharkページにレンダリングされます。

完成したファイルは次のようになります。

~/node_project/controllers/sharks.js

const path = require('path');
const Shark = require('../models/sharks');

exports.index = function (req, res) {
    res.sendFile(path.resolve('views/sharks.html'));
};

exports.create = function (req, res) {
    var newShark = new Shark(req.body);
    console.log(req.body);
    newShark.save(function (err) {
            if(err) {
            res.status(400).send('Unable to save shark to database');
        } else {
            res.redirect('/sharks/getshark');
        }
  });
               };

exports.list = function (req, res) {
        Shark.find({}).exec(function (err, sharks) {
                if (err) {
                        return res.send(500, err);
                }
                res.render('getshark', {
                        sharks: sharks
             });
        });
};

ここではarrow functionsを使用していませんが、独自の開発プロセスでこのコードを反復処理するときに、arrow functionsを含めることをお勧めします。

編集が終了したら、ファイルを保存して閉じます。

次の手順に進む前に、node_projectディレクトリからtreeを再度実行して、この時点でのプロジェクトの構造を表示できます。 今回は、簡潔にするために、-Iオプションを使用してnode_modulesディレクトリを省略するようにtreeに指示します。

tree -I node_modules

追加したことで、プロジェクトの構造は次のようになります。

Output├── Dockerfile
├── README.md
├── app.js
├── controllers
│   └── sharks.js
├── db.js
├── models
│   └── sharks.js
├── package-lock.json
├── package.json
└── views
    ├── css
    │   └── styles.css
    ├── index.html
    └── sharks.html

ユーザー入力を保存してユーザーに返す方法を指示するコントローラーコンポーネントが用意できたので、コントローラーのロジックを実装するビューの作成に進むことができます。

[[step-5 --- using-ejs-and-express-middleware-to-collect-and-render-data]] ==ステップ5—EJSとExpressミドルウェアを使用してデータを収集およびレンダリングする

アプリケーションがユーザーデータを処理できるようにするために、2つのことを行います。1つは、アプリケーションがユーザーの入力データを解析できるようにする組み込みのExpressミドルウェア関数urlencoded()を含めることです。 次に、テンプレートタグをビューに追加して、コード内のユーザーデータとの動的な対話を可能にします。

Expressのurlencoded()関数を使用するには、最初にapp.jsファイルを開きます。

nano app.js

express.static()関数の上に、次の行を追加します。

~/node_project/app.js

...
app.use(express.urlencoded({ extended: true }));
app.use(express.static(path));
...

この関数を追加すると、サメ​​情報フォームから解析済みのPOSTデータにアクセスできるようになります。 extendedオプションでtrueを指定して、アプリケーションが解析するデータのタイプ(ネストされたオブジェクトなどを含む)の柔軟性を高めています。 オプションの詳細については、function documentationを参照してください。

編集が終了したら、ファイルを保存して閉じます。

次に、テンプレート機能をビューに追加します。 まず、npm installとともにejs packageをインストールします。

npm install ejs

次に、viewsフォルダーにあるsharks.htmlファイルを開きます。

nano views/sharks.html

ステップ3では、このページを見て、Mongooseのスキーマとモデルを記述する方法を決定しました。

Shark Info Page

ここで、2つの列layoutを使用するのではなく、ユーザーがサメに関する情報を入力できるフォームを備えた3番目の列を紹介します。

最初のステップとして、既存の列の次元を4に変更して、3つの同じサイズの列を作成します。 現在<div class="col-lg-6">を読み取っている2行でこの変更を行う必要があることに注意してください。 これらは両方とも<div class="col-lg-4">になります。

~/node_project/views/sharks.html

...

Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.
Sawshark

Other sharks are known to be friendly and welcoming!
Sammy the Shark

行と列のレイアウトを含むBootstrapのグリッドシステムの概要については、このintroduction to Bootstrapを参照してください。

次に、ユーザーのサメデータとそのデータをキャプチャするEJSテンプレートタグを含むPOSTリクエストの名前付きエンドポイントを含む別の列を追加します。 この列は、前の列の終了</p>タグと</div>タグの下、および行、コンテナー、およびHTMLドキュメントの終了タグの上に配置されます。 これらの終了タグは既にコード内に配置されています。また、それらにはコメントが付いています。 次のコードを追加して新しい列を作成するときに、それらをそのまま残します。

~/node_project/views/sharks.html

...
       

Enter Your Shark

formタグで、ユーザーのサメデータの"/sharks/addshark"エンドポイントを追加し、それを送信するPOSTメソッドを指定します。 入力フィールドでは、前に定義したSharkモデルに合わせて、"Shark Name"および"Shark Character"のフィールドを指定しています。

sharksコレクションにユーザー入力を追加するには、JavaScript構文とともにEJSテンプレートタグ(<%=%>)を使用して、ユーザーのエントリを新しく作成された適切なフィールドにマップします。資料。 JavaScriptオブジェクトの詳細については、Understanding JavaScript Objectsに関する記事を参照してください。 EJSテンプレートタグの詳細については、EJS documentationを参照してください。

シャーク入力フォームの列を含む3つの列すべてを含むコンテナー全体は、終了すると次のようになります。

~/node_project/views/sharks.html

...

Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.
Sawshark

Other sharks are known to be friendly and welcoming!
Sammy the Shark

Enter Your Shark

編集が終了したら、ファイルを保存して閉じます。

ユーザーの入力を収集する方法ができたので、返されたサメとそれに関連するキャラクター情報を表示するエンドポイントを作成できます。

新しく変更されたsharks.htmlファイルをgetshark.htmlというファイルにコピーします。

cp views/sharks.html views/getshark.html

getshark.htmlを開きます:

nano views/getshark.html

ファイル内で、サメの入力フォームの作成に使用した列を、sharksコレクション内のサメを表示する列に置き換えることで変更します。 この場合も、コードは、前の列の既存の</p>タグと</div>タグと、行、コンテナー、およびHTMLドキュメントの終了タグの間に配置されます。 次のコードを追加して列を作成するときに、これらのタグをそのままにしておいてください。

~/node_project/views/getshark.html

...
       

Your Sharks
    <% sharks.forEach(function(shark) { %>

    Name: <%= shark.name %>

    Character: <%= shark.character %>

    <% }); %>

ここでは、EJSテンプレートタグとforEach() methodを使用して、最近追加されたサメに関する情報を含む、sharksコレクションの各値を出力しています。

sharksコレクションの列を含む、3つの列すべてを含むコンテナー全体は、終了すると次のようになります。

~/node_project/views/getshark.html

...

Some sharks are known to be dangerous to humans, though many more are not. The sawshark, for example, is not considered a threat to humans.
Sawshark

Other sharks are known to be friendly and welcoming!
Sammy the Shark

Your Sharks
    <% sharks.forEach(function(shark) { %>

    Name: <%= shark.name %>

    Character: <%= shark.character %>

    <% }); %>

編集が終了したら、ファイルを保存して閉じます。

作成したテンプレートをアプリケーションで使用するには、app.jsファイルに数行追加する必要があります。 もう一度開きます:

nano app.js

express.urlencoded()関数を追加した場所の上に、次の行を追加します。

~/node_project/app.js

...
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.use(express.urlencoded({ extended: true }));
app.use(express.static(path));

...

app.engineメソッドは、EJSテンプレートエンジンをHTMLファイルにマップするようにアプリケーションに指示し、app.setはデフォルトのビューエンジンを定義します。

app.jsファイルは次のようになります。

~/node_project/app.js

const express = require('express');
const app = express();
const router = express.Router();
const db = require('./db');

const path = __dirname + '/views/';
const port = 8080;

router.use(function (req,res,next) {
  console.log('/' + req.method);
  next();
});

router.get('/',function(req,res){
  res.sendFile(path + 'index.html');
});

router.get('/sharks',function(req,res){
  res.sendFile(path + 'sharks.html');
});

app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.use(express.urlencoded({ extended: true }));
app.use(express.static(path));
app.use('/', router);

app.listen(port, function () {
  console.log('Example app listening on port 8080!')
})

ユーザーデータを動的に操作できるビューを作成したので、次はプロジェクトのルートを作成して、ビューとコントローラーロジックをまとめます。

[[step-6 -—- creating-routes]] ==ステップ6—ルートの作成

アプリケーションのコンポーネントをまとめる最終ステップは、ルートの作成です。 アプリケーションのランディングページへのルートとサメページへの別のルートを含む、機能別にルートを分離します。 sharksルートは、コントローラーのロジックを前のステップで作成したビューと統合する場所になります。

まず、routesディレクトリを作成します。

mkdir routes

次に、このディレクトリにあるindex.jsというファイルを開きます。

nano routes/index.js

このファイルは、最初にexpressrouter、およびpathオブジェクトをインポートし、routerオブジェクトを使用してエクスポートするルートを定義できるようにします。ファイルパスを動的に操作します。 ファイルの先頭に次のコードを追加します。

~/node_project/routes/index.js

const express = require('express');
const router = express.Router();
const path = require('path');

次に、次のrouter.use関数を追加します。この関数は、ルーターのリクエストをログに記録してアプリケーションのルートに渡すmiddleware functionを読み込みます。

~/node_project/routes/index.js

...

router.use (function (req,res,next) {
  console.log('/' + req.method);
  next();
});

アプリケーションのルートへのリクエストはここで最初に送信され、ここからユーザーはアプリケーションのランディングページ、次に定義するルートに移動します。 router.use関数の下に次のコードを追加して、ランディングページへのルートを定義します。

~/node_project/routes/index.js

...

router.get('/',function(req,res){
  res.sendFile(path.resolve('views/index.html'));
});

ユーザーがアプリケーションにアクセスしたときに、最初に送信したいのは、viewsディレクトリにあるindex.htmlランディングページです。

最後に、これらのルートをアプリケーションの他の場所でインポート可能なモジュールとしてアクセスできるようにするには、ファイルの最後に終了式を追加して、routerオブジェクトをエクスポートします。

~/node_project/routes/index.js

...

module.exports = router;

完成したファイルは次のようになります。

~/node_project/routes/index.js

const express = require('express');
const router = express.Router();
const path = require('path');

router.use (function (req,res,next) {
  console.log('/' + req.method);
  next();
});

router.get('/',function(req,res){
  res.sendFile(path.resolve('views/index.html'));
});

module.exports = router;

編集が終了したら、このファイルを保存して閉じます。

次に、sharks.jsというファイルを開いて、ユーザーのサメの入力を処理するために作成したさまざまなエンドポイントとビューをアプリケーションがどのように使用するかを定義します。

nano routes/sharks.js

ファイルの先頭で、expressおよびrouterオブジェクトをインポートします。

~/node_project/routes/sharks.js

const express = require('express');
const router = express.Router();

次に、コントローラーで定義したエクスポートされた関数を操作できるようにするsharkというモジュールをインポートします。

~/node_project/routes/sharks.js

const express = require('express');
const router = express.Router();
const shark = require('../controllers/sharks');

これで、sharksコントローラーファイルで定義したindexcreate、およびlist関数を使用してルートを作成できます。 各ルートは適切なHTTPメソッドに関連付けられます。メインのサメ情報のランディングページをレンダリングしてサメのリストをユーザーに返す場合はGET、新しいサメエントリを作成する場合はPOSTです。

~/node_project/routes/sharks.js

...

router.get('/', function(req, res){
    shark.index(req,res);
});

router.post('/addshark', function(req, res) {
    shark.create(req,res);
});

router.get('/getshark', function(req, res) {
    shark.list(req,res);
});

このファイルの先頭にインポートすることでモジュールにアクセスできるようにしたため、各ルートはcontrollers/sharks.jsの関連関数を使用します。

最後に、これらのルートをrouterオブジェクトに添付してエクスポートし、ファイルを閉じます。

~/node_project/routes/index.js

...

module.exports = router;

完成したファイルは次のようになります。

~/node_project/routes/sharks.js

const express = require('express');
const router = express.Router();
const shark = require('../controllers/sharks');

router.get('/', function(req, res){
    shark.index(req,res);
});

router.post('/addshark', function(req, res) {
    shark.create(req,res);
});

router.get('/getshark', function(req, res) {
    shark.list(req,res);
});

module.exports = router;

編集が終了したら、ファイルを保存して閉じます。

これらのルートをアプリケーションからアクセスできるようにする最後のステップは、それらをapp.jsに追加することです。 そのファイルをもう一度開きます。

nano app.js

db定数の下に、ルートに次のインポートを追加します。

~/node_project/app.js

...
const db = require('./db');
const sharks = require('./routes/sharks');

次に、replaceは、現在routerオブジェクトをマウントするapp.use関数で、次の行を使用します。これにより、sharksルーターモジュールがマウントされます。

~/node_project/app.js

...
app.use(express.static(path));
app.use('/sharks', sharks);

app.listen(port, function () {
        console.log("Example app listening on port 8080!")
})

sharksルーターモジュールを使用してアプリケーションのルートをインポートしているため、このファイルで以前に定義されたルートを削除できるようになりました。

app.jsファイルの最終バージョンは次のようになります。

~/node_project/app.js

const express = require('express');
const app = express();
const router = express.Router();
const db = require('./db');
const sharks = require('./routes/sharks');

const path = __dirname + '/views/';
const port = 8080;

app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.use(express.urlencoded({ extended: true }));
app.use(express.static(path));
app.use('/sharks', sharks);

app.listen(port, function () {
  console.log('Example app listening on port 8080!')
})

編集が終了したら、ファイルを保存して閉じます。

これで、treeを再度実行して、プロジェクトの最終的な構造を確認できます。

tree -I node_modules

プロジェクト構造は次のようになります。

Output├── Dockerfile
├── README.md
├── app.js
├── controllers
│   └── sharks.js
├── db.js
├── models
│   └── sharks.js
├── package-lock.json
├── package.json
├── routes
│   ├── index.js
│   └── sharks.js
└── views
    ├── css
    │   └── styles.css
    ├── getshark.html
    ├── index.html
    └── sharks.html

すべてのアプリケーションコンポーネントを作成して配置したら、テストサメをデータベースに追加する準備ができました。

前提条件の初期サーバーセットアップチュートリアルに従っている場合、ファイアウォールは現在SSHトラフィックのみを許可しているため、ファイアウォールを変更する必要があります。 ポート8080へのトラフィックを許可するには、次のようにします。

sudo ufw allow 8080

アプリケーションを開始します。

node app.js

次に、ブラウザをhttp://your_server_ip:8080に移動します。 次のランディングページが表示されます。

Application Landing Page

Get Shark Infoボタンをクリックします。 サメの入力フォームが追加された以下の情報ページが表示されます。

Shark Info Form

フォームに、選択したサメを追加します。 このデモンストレーションの目的で、Megalodon SharkShark Nameフィールドに追加し、AncientShark Characterフィールドに追加します。

Filled Shark Form

Submitボタンをクリックします。 このサメの情報が表示されたページが表示されます:

Shark Output

また、サメがコレクションに追加されたことを示す出力がコンソールに表示されます。

OutputExample app listening on port 8080!
{ name: 'Megalodon Shark', character: 'Ancient' }

新しいサメのエントリを作成する場合は、Sharksページに戻り、サメを追加するプロセスを繰り返します。

これで、ユーザーがお気に入りのサメに関する情報を追加できる実用的なサメ情報アプリケーションができました。

結論

このチュートリアルでは、MongoDBデータベースを統合し、MVCアーキテクチャパターンを使用してアプリケーションのロジックを書き換えることにより、Nodeアプリケーションを構築しました。 このアプリケーションは、本格的なCRUDアプリケーションの開始点として機能します。

他のコンテキストでのMVCパターンに関するその他のリソースについては、Django Development seriesまたはHow To Build a Modern Web Application to Manage Customer Information with Django and React on Ubuntu 18.04を参照してください。

MongoDBの操作の詳細については、tutorials on MongoDBのライブラリを参照してください。

Related