こんにちは。
今回は、ローカルにPostgreSQLでデータベースを用意して、ExpressでREST APIを作成してみたいと思います。
GETリクエストとPOSTリクエストに対応します。
PostgreSQLでデータベースとテーブルを作成する
データベースの作成
PostgreSQLがローカルにインストールされている前提で進めます。
まずは、ログイン。
psql -U <ユーザーネーム><ユーザーネーム>の部分は、デフォルトだとpostgresのはずです。
パスワードを求められるので、入力してログインします。
ログインできたらデータベースを作成します。
postgres=# CREATE DATABASE express_postgres;データベースの名前は、express_postgresとしました。
データベースが作成できましたので、その中にテーブルを作成しましょう。
productsテーブルの作成
今回はシンプルにproductsテーブルのみを作成します。
まずは先程作成したデータベースexpress_postgresに接続します。
postgres=# \c express_postgres\(バックスラッシュ)cは、データベースに接続するpsqlのコマンドです。
接続できたらproductsテーブルを作ります。
express_postgres=# CREATE TABLE products
(id serial PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price integer NOT NULL);idと商品名(name)と値段(price)のcolumnを作成しました。
idのデータ型をserialにしてあるので、データを入れるごとにidは1ずつ増えていきます。
nameは最大255文字入れられます。NOT NULLなので空欄にはできません。
priceは整数で、こちらもNOT NULLです。
\d productsと打つと、productsテーブルの詳細が見られます。

テーブルの作成ができました。
productsテーブルに商品データを入れる
先ほど作成したproductsテーブルに商品データを入れていきます。
express_postgres=# INSERT INTO products(name, price) VALUES ('赤い帽子', 3980);と打つと、3980円の赤い帽子がproductsテーブルに挿入されます。
データを確認してみましょう。
express_postgres=# select * from products;と打つと、productsテーブルの中のすべてのデータが表示されます。

同様にデータを入れて、今のテーブルはこんな感じです。

これでPostgreSQL側の準備は完了です。
Express generatorでExpress.jsをインストール
Express.jsをインストール
ローカルにプロジェクトフォルダを作って、その中でターミナルにて
npx express-generatorを実行します。
すると各種ファイルと、package.jsonが作られるので、
npm installを実行します。
nodemonを入れる
ついでに開発用にnodemonを入れておきましょう。
npm install --save-dev nodemonと打ってインストールします。
次に、package.jsonの”scripts”を少し修正します。
“start”のコードをコピペして、”dev”を作ります。
“node”の部分を”nodemon”に変えます。
"scripts": {
"start": "node ./bin/www",
"dev": "nodemon ./bin/www"
},
これでターミナルで、
npm run devと打つと、サーバーが立ち上がり、ファイルを修正して保存する度にサーバーが再起動されます。
この状態で、http://localhost:3000/にアクセスするとデフォルトのExpressのページが表示されます。

node-postgresでデータベースと接続する
node-postgresのインストール
node-postgresは、PostgreSQLに接続するnode.jsモジュールです。
npm install pgでインストールします。
dbフォルダを作ってPostgresに接続するコードを書く
インストールが完了したら、Suggested Code Structureを参考に接続用ファイルを作成します。
まずルート直下にdbフォルダを作成して、その下にindex.jsファイルを作成します。
- bin/
- node_modules/
- public/
- routes/
- app.js
- package.json
- package-lock.json
- db/
- index.js <--- このファイルでPostgresに接続するdb/index.jsの中身はこんな感じにしました。
const { Pool } = require("pg");
const pool = new Pool();
module.exports = {
async query(text, params) {
return await pool.query(text, params);
},
};
async・await文を使ってシンプルに仕上げました。
データベースへのアクセス情報を追加する
Connectingのページを参考に、先程のindex.jsにデータベースへのアクセス情報を追加します。
※Github等でコードを公開する際は、.gitignoreやdotenvを使ってアクセス情報が公開されないように気をつけましょう。
ここではURI形式で接続します。このURIはダミーです。
db/index.js
const { Pool } = require("pg");
const connectionString =
"postgresql://dbuser:secretpassword@localhost:5432/express_postgres";
const pool = new Pool({ connectionString });
module.exports = {
async query(text, params) {
return await pool.query(text, params);
},
};・dbuserは、データベースのユーザー名に差し替え
・secretpasswordは、データベースのパスワードに差し替え
・@のところはデータベースのホストの場所で、今回はローカルなのでlocalhost
・:のところはデータベースのポート番号(postgresのデフォルトは5432)
・最後の/以下は、接続するデータベース名
これでPostgresのデータベースに接続する準備ができました。
GETリクエスト周辺のコードを書く
次は、GETリクエストがあった場合に実行されるコードを書いていきます。
リクエスト: app.js -> Route -> Service -> Model -> PostgreSQL
レスポンス: app.js <- Route <- Service <- Model <- PostgreSQLという感じの流れを作ります。
Modelの作成
先ほど作成したdb/index.jsを利用して、クエリ文をかいてデータベースからデータを取り出すModelを用意します。
ルート直下にmodelsというフォルダを用意して、その下にproducts.jsを作成します。
models/products.js
const db = require("../db");
module.exports = class ProductsModel {
async getProducts() {
const text = `SELECT id, name, price from products`;
const values = [];
try {
const res = await db.query(text, values);
console.log(res.rows);
if (res?.rows[0]) {
return res.rows;
}
return [];
} catch (err) {}
}
};class ProductsModelを作成してexportします。
class ProductsModelの中にgetProducts()を作成して、先程用意したdb/index.jsを使ってデータベースにクエリ文を送ります。
返ってきたres.rowsの中身が空でなければres.rowsを返します。空であれば空のArrayを返します。
うまく行けば、productsテーブルにある全てのid, name, priceが返って来ます。
これで一旦GETリクエストのModelはできました。
Serviceの作成
次はModelとRouteをつなぐ、Serviceを作成します。
ルート直下にservicesというフォルダを作成し、その下にproducts.jsを作成します。
services/products.js
const productsModel = require("../models/products");
const productsModelInstance = new productsModel();
module.exports = class productsService {
async getProducts() {
try {
const res = await productsModelInstance.getProducts();
return res;
} catch (err) {}
}
};
こちらでも、class productsServiceを作成してexportしています。
先程作ったproductsModelを呼び出して、インスタンス化してgetProducts()を使っています。
返ってきたものを、更に返します。この場合はproductsのArrayが返ってくるはずです。
これでGETリクエストのServiceも完成。
Routeの作成
次はproducts用のrouteを作成します。
既に存在するroutesフォルダの下にproducts.jsを作成します。
routes/products.js
var express = require("express");
var router = express.Router();
const productsService = require("../services/products");
const productsServiceInstance = new productsService();
router.get("/", async function (req, res, next) {
try {
const response = await productsServiceInstance.getProducts();
res.send(response);
} catch (err) {}
});
module.exports = router;ここではroutesのindex.jsやusers.jsをコピペして改変しました。
express.Router()を使ってgetリクエストのrouteを作成し、最終行でexportしています。
先程作ったproductServiceをインスタンス化して、getProducts()を使用しています。
そして返ってきたものを、res.send()を使ってレスポンスとして返しています。
これでGETリクエストのRoutesも完了です。
app.jsにrouteを追加する
最後に、既に存在するapp.jsに、先程作ったroutes/products.jsを追加します。
app.js
var createError = require("http-errors");
<中略>
var indexRouter = require("./routes/index");
var usersRouter = require("./routes/users");
const productsRouter = require("./routes/products");
var app = express();
<中略>
app.use("/", indexRouter);
app.use("/users", usersRouter);
app.use("/api/products", productsRouter);
<中略>
module.exports = app;上の方で、productsRouterを用意して、真ん中あたりでapp.use()を使って、”/api/products”と対応させています。
これで、http://localhost:3000/api/productsにGETリクエストを送ると、商品リストのJSONデータが送られてくるはずです。
PostmanでGETリクエストを送ってみる
PostmanはAPI作成に使える大変便利なツールです。
これを使ってGETリクエストを送ってみたいと思います。
Postman上でワークスペースを作って、http://localhost:3000/api/productsにGETリクエストを送信します。

すると、JSONデータが返ってきます。

リクエストが成功した「200 OK」とともに、商品データのid, name, priceが、それぞれArray形式で返ってきましたね。
次は、POSTリクエストでデータベースのproductsテーブルに新規商品を追加してみましょう。
POSTリクエスト周辺のコードを書く
次は、POSTリクエストがあった場合に実行されるコードを書いていきます。
GETリクエスト同様に、
リクエスト: app.js -> Route -> Service -> Model -> PostgreSQL
レスポンス: app.js <- Route <- Service <- Model <- PostgreSQLという感じの流れを作ります。
GETリクエストのときに作成したファイルに加筆していきます。
Modelの作成
まずはModelから。
models/products.js
const db = require("../db");
module.exports = class ProductsModel {
async getProducts() {
<省略>
}
async createProduct({ name, price }) {
const text = `INSERT INTO
products(name, price)
VALUES($1, $2)
RETURNING *`;
const values = [name, price];
try {
const res = await db.query(text, values);
if (res?.rows[0]) {
return res.rows[0];
}
return {};
} catch (err) {}
}
};class ProductsModel の中に、createProduct()を追記しました。
textの中には、SQL文が書いてあります。
$1, $2とあるのはプレースホルダーで、values Arrayの順番に対応して自動的に置き換わります。
そしてレスポンスを返します。
次はServiceの作成に移りましょう。
Serviceの作成
ModelとRouteをつなぐ、Serviceです。
既存のファイルに追記します。
services/products.js
const productsModel = require("../models/products");
const productsModelInstance = new productsModel();
module.exports = class productsService {
async getProducts() {
try {
const res = await productsModelInstance.getProducts();
return res;
} catch (err) {}
}
async createProduct(data) {
try {
const res = await productsModelInstance.createProduct(data);
return res;
} catch (err) {}
}
};createProduct()を追記しました。
GETリクエストのコードとほとんど変わらないですね。
dataは、POSTリクエストで送られてくるデータオブジェクトで、Modelの中でnameとpriceに分解されます。
次はRouteに行きましょう。
Routeの作成
Routeも既存の同じファイルに追記します。
GETリクエストのときと大体同じですが、送られてきた商品データを取得しなくてはいけません。
routes/products.js
<省略>
const productsServiceInstance = new productsService();
router.get("/", async function (req, res, next) {
<省略>
});
router.post("/", async function (req, res, next) {
try {
const data = req.body;
const response = await productsServiceInstance.createProduct(data);
res.send(response);
} catch (err) {}
});
module.exports = router;
req.bodyから、リクエストのbodyを取得して、dataに入れました。
これが商品データのオブジェクトで、nameとpriceが入っているはずです。
あとは先程作ったcreateProduct(data)を発動して、返ってきたものをres.send(response)で返すだけです。
app.jsには、GETリクエスト周辺で、すでにroute追加済みなので、もうPOSTリクエストができるはずです。
試してみましょう。
PostmanでPOSTリクエストを送ってみる
Postmanを使います。
今度はPOSTリクエストなのでPOSTを選択します。
URLはGETリクエストと同じ、http://localhost:3000/api/productsでOKです。
Sendボタンを押す前に、送信する商品データを作成します。

URL入力欄の下部のBodyを選んでrawを選んでJSONを選びます。
すると、JSON入力欄が現れるので、JSON形式で商品データを入力します。
今回書いたコードに合わせて、nameとpriceです。
idはデータベース側で自動的に+1の数字が付与されます。
ではSendボタンを押してみましょう。

「200 OK」と、今回作成した商品データが返ってきました。
Postgres側でも確認してみる
きちんと商品データが追加されているかをPostgres側でも確認してみます。

きちんと青いスニーカー(12900円)が追加されていますね。
これでPOSTリクエスト周辺の記述は終わりです。
動作の確認
最後に、もういちどGETリクエストをしてみましょう。


はい、返ってきたJSONオブジェクトに新しい商品が追加されていますね。
こんな感じでExpress.jsとPostgreSQLでREST APIが完成しました。


コメント