Webの概念としてクライアントから送られたリクエストをサーバが受け取り、サーバはデータベースとやり取りを行い、結果をクライアントへレスポンスとして返します。
今回はこの一連のやり取りのサーバ、データベース間の処理に注目して記事を書いていきます。
サーバはExpress、データベースはmongoDBを使って、処理自体はmongooseというライブラリを使って実装していきます。
メインアプリケーションファイル
まずはapp.jsです。
const express = require('express');
const app = express();
const tasksRouter = require('./routes/tasks');
const connectDB = require('./db/connect');
require('dotenv').config();
app.use(express.json());
app.use(express.static('./public'));
const port = 5001;
// ルーティング設計
app.use('/api/v1/tasks', tasksRouter);
//データベースと接続
const start = async () => {
try {
await connectDB(process.env.MONGO_URL);
app.listen(port, () => {
console.log(`サーバーがポート${port}で起動しました`);
});
} catch (error) {
console.error('データベース接続エラー:', error);
}
};
start();
- ポート5001でサーバーを起動
/api/v1/tasks
パスでタスク関連のAPIエンドポイントを設定- 環境変数からMongoDB接続URLを取得(
process.env.MONGO_URL
) - express.json()でJSONデータの解析を有効化
データベース接続モジュール
次はdb > connect.jsです。このファイルではMongooseによるMongoDB接続機能を担っています。
const mongoose = require('mongoose');
const connectDB = (url) => {
return mongoose
.connect(url)
.then(() => console.log('データベースと接続中...'))
.catch((err) => console.log(err));
};
module.exports = connectDB;
- mongoose.connect(url)でMongoDB Atlas/ローカルDBに接続
- Promiseチェーンで接続状況をログ出力
app.js
でこの関数を呼び出してDB接続を確立
データモデル定義
次はmodels > Task.jsです。これはスキーマを定義するファイルです。
const mongoose = require('mongoose');
const TaskSchema = new mongoose.Schema({
name: {
type: String,
required: [true, 'タスク名を入力してください'],
trim: true,
maxlength: [20, 'タスク名は20文字以内で入力してください'],
},
completed: {
type: Boolean,
default: false,
},
});
module.exports = mongoose.model('Task', TaskSchema);
- バリデーション機能(必須項目、文字数制限)
- デフォルト値の設定
- MongoDB Collection “tasks”にマッピング
ルーティング定義
routes > tasks.jsです。このファイルはルーティング設定をしています。
const express = require('express');
const router = express.Router();
const {
getAllTasks,
createTask,
getSingleTask,
updateTask,
deleteTask,
} = require('../controllers/tasks');
router.get('/', getAllTasks);
router.post('/', createTask);
router.get('/:id', getSingleTask);
router.patch('/:id', updateTask);
router.delete('/:id', deleteTask);
module.exports = router;
- GET /api/v1/tasks – 全タスク取得
- POST /api/v1/tasks – 新規タスク作成
- GET /api/v1/tasks/:id – 特定タスク取得
- PATCH /api/v1/tasks/:id – タスク更新
- DELETE /api/v1/tasks/:id – タスク削除
ビジネスロジック
controllers > tasks.jsです。各APIエンドポイントの実際の処理を実装強いているファイルです。
const Task = require('../models/Tasks');
const getAllTasks = async (req, res) => {
try {
const allTasks = await Task.find({});
res.status(200).json(allTasks);
} catch (error) {
res.status(500).json(error);
}
};
const createTask = async (req, res) => {
try {
const createTask = await Task.create(req.body);
res.status(200).json(createTask);
} catch (error) {
res.status(500).json(error);
}
};
const getSingleTask = async (req, res) => {
try {
const getSingleTask = await Task.findOne({ _id: req.params.id });
if (!getSingleTask) {
return res.status(404).json(`ID:${req.params.id}のタスクは存在しません`);
}
res.status(200).json(getSingleTask);
} catch (error) {
res.status(500).json(error);
}
};
const updateTask = async (req, res) => {
try {
const updateTask = await Task.findOneAndUpdate(
{ _id: req.params.id },
req.body,
{ new: true }
);
if (!updateTask) {
return res.status(404).json(`ID:${req.params.id}のタスクは存在しません`);
}
res.status(200).json(updateTask);
} catch (error) {
res.status(500).json(error);
}
};
const deleteTask = async (req, res) => {
try {
const deleteTask = await Task.findOneAndDelete({ _id: req.params.id });
if (!deleteTask) {
return res.status(404).json(`ID:${req.params.id}のタスクは存在しません`);
}
res.status(200).json(deleteTask);
} catch (error) {
res.status(500).json(error);
}
};
module.exports = {
getAllTasks,
createTask,
getSingleTask,
updateTask,
deleteTask,
};
- getAllTasks
Task.find({}) – 全タスクをMongoDBから取得
- createTask
Task.create(req.body) – リクエストボディからタスク作成
- getSingleTask
Task.findOne({ _id: req.params.id }) – ID指定でタスク取得
- updateTask
Task.findOneAndUpdate() – ID指定でタスク更新
{ new: true }
オプションで更新後のデータを返却
- deleteTask
Task.findOneAndDelete() – ID指定でタスク削除
まとめ
アプリケーション起動
まずapp.jsがconnectDB()を呼び出し、connect.jsでMongoose経由でMongoDBと接続。接続成功後、Expressサーバがポート5001で起動し、クライアントからのHTTPリクエストを待機という流れになっています。
APIリクエスト処理
クライアントがHTTPリクエストを送信し、routes > tasks.jsファイルでルーティング。controllers > tasks.jsの対応する関数が実行され、Mongooseを通じてMongoDBを操作。結果をJSON形式でクライアントに返却という流れになっています。