やること
Node.jsのMVCフレームワークExpressとNoSQLのMongoDBを使って、ユーザ情報の登録・変更・削除ができる簡単なRestAPIを作る。
リクエストやレスポンスはjsonで(NoSQLとの相性抜群)。
MongoDBはDockerコンテナ上で起動させる。
準備
Docker上でMongoDB起動
MongoDBをDockerコンテナ上で起動する。
直に入れてもいいが、せっかくなのでDocker使ってみる。
# Dockerインストール
$ brew install docker --cask
# MongoDBイメージ取得
$ docker pull mongo
# コンテナを作成して起動
# ホストOS側は27018ポート、コンテナ側は27017ポート(MongoDBのデフォルト)を使用
$ docker run -p 27018:27017 --name mongo-test -d mongo
Node.jsプロジェクト作成
ベースとなるプロジェクトを作って環境構築する。
Docker起動中かと思うので、別のターミナルを起動する。
# ディレクトリ作成
$ mkdir test-app
# 初期化処理(問合せ無しでpackage.json作成)
$ npm init -y
# 必要nodeモジュール(expressとmongoDB操作用モジュール)をインストール
$ npm install express mongoose
Model作成
スキーマとなるUserModelを定義する。
# ディレクトリ作成
$ mkdir server
$ cd server
$ mkdir models
# Model定義JavaScript作成
$ touch models/user.js
user.jsをVSCodeとかで開いて編集する。
肝心のModelは今回、ユニークなID、名前、年齢の3つのフィールドを持たせる。
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
id: {
type: String,
required: true,
unique: true
},
name: { type: String },
age: { type: Number}
});
module.exports = mongoose.model('users', userSchema);
Router&Controller作成
Modelを利用して実際にHTTPリクエストが来た際にどう振舞うかを定義するRouterと、全体を制御するControllerを定義する。
今回は小規模なので、分けずにまとめてserver.jsとする。
# ディレクトリ移動
$ cd ..
# Router&Controller定義JavaScript作成
$ touch server.js
server.jsをVSCodeとかで開いて編集する。
httpリクエストは3001番ポートで待ち受けるとする。
コードを少なくしたかったので、登録以外はエラー処理を端折ってます。
const express = require('express');
const mongoose = require('mongoose');
const User = require('./models/user');
// DB接続
mongoose.connect('mongodb://localhost:27018/sampledb');
const app = express();
app.use(express.json({extended: true}));
// ユーザ情報登録
app.post('/users', (req, res) => {
const user = new User(req.body);
user.save((err, addedUser) => {
if (err)
return res.status(400).json({
errorMessage: 'failed to add the user.'
});
res.send(addedUser);
});
});
// ユーザ情報取得(全件)
app.get('/users', (req, res) => {
User.find({}, (err, users) => {
res.send(users);
});
});
// ユーザ情報取得(ID指定)
app.get('/users/:id', (req, res) => {
const params = req.params.id;
User.find({id: params}, (err, user) => {
res.send(user);
});
});
// ユーザ情報削除(全件)
app.delete('/users', (req, res) => {
User.remove({}, err => {
res.send(true);
});
});
// ユーザ情報削除(ID指定)
app.delete('/users/:id', (req, res) => {
const params = req.params.id;
User.remove({id: params}, (err, deletedUser) => {
res.send(deletedUser);
});
});
// ポート3001番でlisten
app.listen(3001, () => {
console.log(`Server up on 3001`);
});
サーバ起動
$ node server.js
動作確認(curlコマンド)
curlコマンドでユーザ情報の登録・取得・削除をやってみる。
_id
と__v
はMongoDBが自動付与するフィールドで、それぞれオブジェクトID、バージョン管理用として使われる。
# Allen登録
$ curl -X POST -H 'Content-Type:application/json' -d '{"id":"001","name":"Allen","age":20}' http://localhost:3001/users
# Allen登録結果
{"_id":"607bce198776e444bd55422b","id":"001","name":"Allen","age":20,"__v":0}%
# Yuki登録
$ curl -X POST -H 'Content-Type:application/json' -d '{"id":"002","name":"Yuki","age":26}' http://localhost:3001/users
# Yuki登録結果
{"_id":"607c3bf502ac68477a41ee10","id":"002","name":"Yuki","age":26,"__v":0}%
# 全件取得
$ curl -X GET http://localhost:3001/users
# 取得結果
[{"_id":"607bce198776e444bd55422b","id":"001","name":"Allen","age":20,"__v":0},{"_id":"607c3bf502ac68477a41ee10","id":"002","name":"Yuki","age":26,"__v":0}]%
# IDを指定して取得
$ curl -X GET http://localhost:3001/users/001
# 取得結果
[{"_id":"607bce198776e444bd55422b","id":"001","name":"Allen","age":20,"__v":0}]%
# IDを指定して削除
$ curl -X DELETE http://localhost:3001/users/001
# 削除結果
{"n":1,"ok":1,"deletedCount":1}%
# 削除確認のため全件取得
$ curl -X GET http://localhost:3001/users
# 残ってるのはYukiだけ
[{"_id":"607c3bf502ac68477a41ee10","id":"002","name":"Yuki","age":26,"__v":0}]%
# 全件削除
$ curl -X DELETE http://localhost:3001/users
# 削除結果
true%
# 削除確認のため全件取得
$ curl -X GET http://localhost:3001/users
# 何も残っていない
[]%
動作確認(API Tester)
curlコマンドだと視覚的に分かりづらいので、Chrome拡張のTalend API Testerを使って、視覚的に確認する。
こちらでは登録と全件取得だけ確認してみる。
この後、同じ要領でYukiも登録したとして、次は全件取得。
こんな感じで確認できた。
もちろん、METHODを変えることでDELETEも可能。
これで一通り、DBを操作する簡単なRestAPIを作成できた。
応用としてやってみたいこと
- フロントエンドをReactとかで作りたい。
- 今回DockerはMongoDBでしか使わなかったが、Node.jsそのものからDocker上で環境構築したい。VSCodeでDockerコンテナ上のワークスペースも編集できるらしい(参考)。
- TypeScriptで書けるようにしたい(参考)。
参考サイト
初級JavascriptフルスタックエンジニアのためのReactとExpressの同時開発チュートリアル
MongoDB(Mongoose)上級者への道
curlコマンドを使った操作