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

前書き

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

このチュートリアルでは、https://www.mongodb.com/ [MongoDB]データベースを既存のNodeアプリケーションと統合します。 データ要件にスケーラビリティと柔軟性が含まれている場合、MongoDBのようなhttps://www.digitalocean.com/community/tutorials/digitalocean-community-glossary#nosql[NoSQLデータベース]が役立ちます。 MongoDBは、https://www.digitalocean.com/community/tutorials/an-introduction-to-json [JSON]オブジェクトと非同期に動作するように設計されているため、Nodeとの統合も良好です。

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

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

image:https://assets.digitalocean.com/articles/node_mongo/shark_added.png [サメ出力]

前提条件

  • Ubuntu 18.04を実行するローカル開発マシンまたはサーバー、および「+ sudo +」権限とアクティブなファイアウォールを持つ非ルートユーザー。 18.04サーバーでこれらをセットアップする方法のガイダンスについては、https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04 [初期サーバーセットアップガイド]を参照してください。

  • Node.jsおよびhttps://www.npmjs.com/[npm]をマシンまたはサーバーにインストールし、https://www.digitalocean.com/community/tutorials/how-to-install-node-js-onに従ってください-ubuntu-18-04#installing-using-a-ppa [NodeSourceが管理するPPAを使用したインストールに関するこれらの手順]。

  • Ubuntu 18.04にMongoDBをインストールする方法のステップ1に従って、マシンまたはサーバーにインストールされたMongoDB 。

ステップ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:  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 +`データベースへの無制限のアクセスが原因で、シェルを開くと管理警告が表示されます。 このアクセスの制限の詳細については、https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-mongodb-on-ubuntu-16-04 [MongoDBをインストールして保護する方法を参照してください。 Ubuntu 16.04]で、実稼働セットアップに移行する場合に使用します。

現時点では、 + admin +`データベースへのアクセスを使用して、https://docs.mongodb.com/manual/reference/built-in-roles/#userAdminAnyDatabase [+ userAdminAnyDatabase +`]権限を持つユーザーを作成できます。これにより、アプリケーションのデータベースへのパスワードで保護されたアクセスが許可されます。

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

use admin

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

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

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

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

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

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

exit

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

ステップ2-プロジェクトへのMongooseおよびデータベース情報の追加

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

非ルートユーザーのホームディレクトリで、https://github.com/doからhttps://github.com/do-community/nodejs-image-demo [`+ nodejs-image-demo +`リポジトリ]を複製します。 -community [DigitalOcean Community GitHubアカウント]。 このリポジトリには、https://www.digitalocean.com/community/tutorials/how-to-build-a-node-js-application-with-docker [Node.jsアプリケーションの構築方法]で説明されているセットアップのコードが含まれています。 Docker]。

リポジトリを `++`というディレクトリにクローンします:

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

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

cd

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

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

tree

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

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

チュートリアルを進めていくと、このプロジェクトにディレクトリを追加し、 `+ tree +`は進捗を追跡するのに役立つコマンドになります。

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

npm install mongoose

このコマンドは、プロジェクトの + package.json +`ファイルにリストされている依存関係を使用して、プロジェクトディレクトリに `+ node_modules +`ディレクトリを作成し、そのディレクトリに `+ mongoose +`を追加します。 また、 `+ package.json`ファイルにリストされている依存関係に + mongoose`を追加します。 `+ package.json +`の詳細については、https://www.digitalocean.com/community/tutorials/how-to-build-a-node-js-application-with-docker#step-1を参照してください。 -%E2%80%94-installing-your-application-dependencies [Step 1] in https://www.digitalocean.com/community/tutorials/how-to-build-a-node-js-application-with- docker [DockerでNode.jsアプリケーションを構築する方法]。

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

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

nano db.js

まず、 + require +`関数を使用して、 `+ mongoose + moduleをインポートします。

〜/ node_project / db.js

const mongoose = require('mongoose');

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

次に、次のhttps://www.digitalocean.com/community/tutorials/understanding-variables-scope-hoisting-in-javascript#constants[constants]を追加して、Mongoの接続URIの情報を定義します。 ユーザー名とパスワードはオプションですが、データベースに認証を要求できるようにそれらを含めます。 以下にリストされているユーザー名とパスワードを自分の情報に置き換えてください。必要に応じて、データベースを `+ '' +`以外のものに呼び出してください。

〜/ node_project / db.js

const mongoose = require('mongoose');

const MONGO_USERNAME = '';
const MONGO_PASSWORD = '';
const MONGO_HOSTNAME = '127.0.0.1';
const MONGO_PORT = '27017';
const MONGO_DB = '';

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

最後に、URIの定数を定義し、https://mongoosejs.com/docs/api.html#connection_Connection [+ 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で、ユーザーの `+ authSource `を ` admin `データベースとして指定していることに注意してください。 接続文字列でユーザー名を指定したため、これが必要です。 ` mongoose.connect()`で ` useNewUrlParser +`フラグを使用すると、Mongoのhttps://mongoosejs.com/docs/deprecations.html[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 path = __dirname + '/views/';
...

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

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

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

ステップ3-Mongooseスキーマとモデルの作成

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

image:https://assets.digitalocean.com/articles/docker_node_image/sharks.png [サメ情報ページ]

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

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

mkdir models

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

nano models/sharks.js

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

〜/ node_project / models / sharks.js

const mongoose = require('mongoose');

この下に、サメスキーマのベースとして使用する `+ Schema +`オブジェクトを定義します。

〜/ node_project / models / sharks.js

const mongoose = require('mongoose');

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

〜/ node_project / models / sharks.js

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

この定義には、ユーザーから期待される入力の種類に関する情報が含まれます。この場合、https://www.digitalocean.com/community/tutorials/understanding-data-types-in-javascript#strings [string]-およびその入力が必要かどうか。

最後に、Mongooseのhttps://mongoosejs.com/docs/api.html#mongoose_Mongoose-model [+ model()+ function]を使用して `+ Shark +`モデルを作成します。 このモデルを使用すると、コレクションからドキュメントを照会し、新しいドキュメントを検証できます。 ファイルの下部に次の行を追加します。

〜/ node_project / models / sharks.js

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

この最後の行は、https://nodejs.org/api/modules.html#modules_exports_shortcut [+ 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 +`スキーマとモデルを配置したら、アプリケーションがユーザー入力を処理する方法を決定するロジックの作業を開始できます。

ステップ4-コントローラーの作成

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

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

mkdir controllers

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

nano controllers/sharks.js

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

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

〜/ node_project / controllers / sharks.js

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

次に、Nodeのhttps://nodejs.org/api/modules.html#modules_exports_shortcut [`+ exports +`ショートカット]を使用してコントローラーモジュールとともにエクスポートする一連の関数を作成します。 これらの機能には、ユーザーのサメデータに関連する3つのタスクが含まれます。

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

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

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

開始するには、入力フォームのあるサメのページを表示するための `+ index`関数を作成します。 この関数をインポートの下に追加します。

〜/ node_project / controllers / sharks.js

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

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

〜/ 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 +」と呼ばれる新しいサメドキュメントオブジェクトを作成します。 https://developer.mozilla.org/en-US/docs/Web/API/Console/log [+ console.log +` method]を追加して、サメのエントリをコンソールに出力し、それを確認しました。 POSTメソッドは意図したとおりに動作しますが、必要に応じてこれを省略してもかまいません。

+ newShark +`オブジェクトを使用して、 `+ create +`関数はMongooseのhttps://mongoosejs.com/docs/api.html#model_Model-save [+ model.save()`メソッド]を呼び出して、 ` Shark `モデルで定義したキーを使用した新しいサメドキュメント。 このhttps://developer.mozilla.org/en-US/docs/Glossary/Callback_function [コールバック関数]は、http://thenodeway.io/posts/understanding-error-first-callbacks/ [標準ノードコールバックパターン]に従います。 : ` callback(error、results)`。 エラーが発生した場合、ユーザーにエラーを報告するメッセージを送信し、成功した場合はhttps://expressjs.com/en/api.html#res.redirect[` 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
            });
       });
};

この関数は、Mongooseのhttps://mongoosejs.com/docs/api.html#model_Model.find [+ model.find()+ method]で + Shark +`モデルを使用して、入力されたサメを返します+ sharks `コレクション。 これは、Mongooseのhttps://mongoosejs.com/docs/api.html#query_Query-exec [`を使用して、クエリオブジェクト(この場合は` + sharks + `コレクション内のすべてのエントリ)を約束として返すことで実行されます。 + exec() `関数]。 エラーの場合、コールバック関数は500エラーを送信します。

`+ sharks `コレクションで返されるクエリオブジェクトは、https://ejs.co/ [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
            });
       });
};

ここではhttps://www.digitalocean.com/community/tutorials/how-to-define-functions-in-javascript#arrow-functions [矢印関数]を使用していませんが、それらを含めることをお勧めします。独自の開発プロセスでこのコードを繰り返しながら。

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

次のステップに進む前に、 `+`ディレクトリから ` 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

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

ステップ5-EJSおよびExpressミドルウェアを使用してデータを収集およびレンダリングする

アプリケーションがユーザーデータを操作できるようにするために、2つのことを行います。最初に、組み込みのExpressミドルウェア関数https://expressjs.com/en/4x/api.html#express.urlencoded [`を組み込みます。 + urlencoded()+ `]。これにより、アプリケーションはユーザーの入力データを解析できます。 次に、テンプレートタグをビューに追加して、コード内のユーザーデータとの動的な対話を可能にします。

Expressの `+ urlencoded()`関数を使用するには、まず ` app.js`ファイルを開きます:

nano app.js

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

〜/ node_project / app.js

...

app.use(express.static(path));
...

この関数を追加すると、サメ​​情報フォームから解析済みのPOSTデータにアクセスできるようになります。 アプリケーションが解析するデータの種類(ネストされたオブジェクトなどを含む)の柔軟性を高めるために、「+ true 」と「 extended +」オプションを指定しています。 オプションの詳細については、https://expressjs.com/en/4x/api.html#express.urlencoded [関数ドキュメント]をご覧ください。

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

次に、テンプレート機能をビューに追加します。 まず、https://www.npmjs.com/package/ejs [+ ejs + package]を `+ npm install +`でインストールします。

npm install ejs

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

nano views/sharks.html

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

image:https://assets.digitalocean.com/articles/docker_node_image/sharks.png [サメ情報ページ]

2列のhttps://getbootstrap.com/docs/4.1/layout/grid/[layout]ではなく、ユーザーがサメに関する情報を入力できるフォームを含む3列目を紹介します。

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

〜/ node_project / views / sharks.html

...
<div class="container">
   <div class="row">
       <div class="col-lg-">
           <p>
               <div class="caption">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.
               </div>
               <img src="https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg" alt="Sawshark">
           </p>
       </div>
       <div class="col-lg-">
           <p>
               <div class="caption">Other sharks are known to be friendly and welcoming!</div>
               <img src="https://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">
           </p>
       </div>
   </div>
 </div>

</html>

行と列のレイアウトを含むBootstrapのグリッドシステムの概要については、https://www.taniarascia.com/what-is-bootstrap-and-how-do-i-use-it/ [Bootstrapの紹介]を参照してください。 ]。

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

〜/ node_project / views / sharks.html

...
      </p>
  </div>
<div class="col-lg-4">
           <p>
               <form action="/sharks/addshark" method="post">
                   <div class="caption">Enter Your Shark</div>
                   <input type="text" placeholder="Shark Name" name="name" <%=sharks[i].name; %>
                   <input type="text" placeholder="Shark Character" name="character" <%=sharks[i].character; %>
                   <button type="submit">Submit</button>
               </form>
           </p>
       </div>
   </div>
</div>

</html>

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

ユーザー入力を + sharks +`コレクションに追加するには、JavaScript構文とともにEJSテンプレートタグ( `+ <%= ++%> +)を使用して、ユーザーのエントリを新しく作成されたドキュメント。 JavaScriptオブジェクトの詳細については、https://www.digitalocean.com/community/tutorials/understanding-objects-in-javascript [JavaScriptオブジェクトについて]の記事をご覧ください。 EJSテンプレートタグの詳細については、https://ejs.co/#docs [EJS documentation]をご覧ください。

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

〜/ node_project / views / sharks.html

...
<div class="container">
   <div class="row">
       <div class="col-lg-4">
           <p>
               <div class="caption">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.
               </div>
               <img src="https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg" alt="Sawshark">
           </p>
       </div>
       <div class="col-lg-4">
           <p>
               <div class="caption">Other sharks are known to be friendly and welcoming!</div>
               <img src="https://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">
           </p>
       </div>
   <div class="col-lg-4">
           <p>
               <form action="/sharks/addshark" method="post">
                   <div class="caption">Enter Your Shark</div>
                   <input type="text" placeholder="Shark Name" name="name" <%=sharks[i].name; %>
                   <input type="text" placeholder="Shark Character" name="character" <%=sharks[i].character; %>
                   <button type="submit">Submit</button>
               </form>
           </p>
       </div>
   </div>
 </div>

</html>

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

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

新しく変更された + 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

...
      </p>
  </div>
<div class="col-lg-4">
          <p>
             <div class="caption">Your Sharks</div>
                 <ul>
                    <% sharks.forEach(function(shark) { %>
                       <p>Name: <%= shark.name %></p>
                       <p>Character: <%= shark.character %></p>
                    <% }); %>
                 </ul>
           </p>
       </div>
   </div>
</div>

</html>

ここではEJSテンプレートタグとhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach [+ forEach()+ method]を使用して各値を出力しています`+ sharks +`コレクションに、最後に追加されたサメに関する情報を含めます。

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

〜/ node_project / views / getshark.html

...
<div class="container">
   <div class="row">
       <div class="col-lg-4">
           <p>
               <div class="caption">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.
               </div>
               <img src="https://assets.digitalocean.com/articles/docker_node_image/sawshark.jpg" alt="Sawshark">
           </p>
       </div>
       <div class="col-lg-4">
           <p>
               <div class="caption">Other sharks are known to be friendly and welcoming!</div>
               <img src="https://assets.digitalocean.com/articles/docker_node_image/sammy.png" alt="Sammy the Shark">
           </p>
       </div>
   <div class="col-lg-4">
           <p>
             <div class="caption">Your Sharks</div>
                 <ul>
                    <% sharks.forEach(function(shark) { %>
                       <p>Name: <%= shark.name %></p>
                       <p>Character: <%= shark.character %></p>
                    <% }); %>
                 </ul>
           </p>
       </div>
   </div>
 </div>

</html>

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

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

nano app.js

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

〜/ node_project / app.js

...


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

...

https://expressjs.com/en/4x/api.html#app.engine [+ app.engine +]メソッドは、アプリケーションにEJSテンプレートエンジンをHTMLファイルにマップするよう指示しますが、https://expressjs.com /en/4x/api.html#app.set [+ 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!')
})

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

ステップ6-ルートの作成

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

最初に、 `+ routes +`ディレクトリを作成します:

mkdir routes

次に、このディレクトリで `+ index.js +`というファイルを開きます:

nano routes/index.js

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

〜/ node_project / routes / index.js

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

次に、次の「+ router.use +」関数を追加します。これは、ルーターのリクエストをログに記録してアプリケーションに渡すhttps://expressjs.com/en/guide/writing-middleware.html [ミドルウェア関数]を読み込みますルート:

〜/ 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();

これで、 + sharks in`コントローラーファイルで定義した + index + + create + 、および + 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');

次に、 + router`オブジェクトを現在マウントしている + app.use + 関数を次の行で*置換*します。これにより、 + sharks`ルーターモジュールがマウントされます。

〜/ node_project / app.js

...
app.use(express.static(path));


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://:8080+」に移動します。 次のランディングページが表示されます。

image:https://assets.digitalocean.com/articles/docker_node_image/landing_page.png [アプリケーションのランディングページ]

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

image:https://assets.digitalocean.com/articles/node_mongo/shark_form.png [サメ情報フォーム]

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

image:https://assets.digitalocean.com/articles/node_mongo/shark_filled.png [サメの塗りつぶしフォーム]

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

image:https://assets.digitalocean.com/articles/node_mongo/shark_added.png [サメ出力]

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

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

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

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

結論

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

他のコンテキストでのMVCパターンの詳細については、https://www.digitalocean.com/community/tutorial_series/django-development [Django Development series]またはhttps://www.digitalocean.com/community/tutorialsをご覧ください。 / how-to-build-a-modern-web-application-to-manage-customer-information-with-django-and-react-on-ubuntu-18-04 [顧客情報を管理するための最新のWebアプリケーションを構築する方法Ubuntu 18.04でDjangoとReactを使用]。

MongoDBの操作の詳細については、https://www.digitalocean.com/community/tags/mongodb?type = tutorials [MongoDBのチュートリアル]のライブラリを参照してください。

Related