一覧・詳細をDB化
呼び出す側は変えない
第2章のつくる回で、データ層を分けておいた理由がここで効きます。
プレーンテキスト
リクエスト → ルート → データ層 → 応答差し替えるのはデータ層の中身だけです。ルートの側は、これまでどおり「一覧をください」と頼むだけで、その裏がファイルなのかデータベースなのかを知りません。
絞り込みを SQL に任せる
第5章では、全件を配列に読んでから filter で絞っていました。データベースがあれば、絞り込み自体を任せられます。
JavaScript
// これまで
const found = items.filter((item) => item.price >= 3000);
// これから
const found = db.prepare("SELECT * FROM items WHERE price >= ?").all(3000);違いは速さです。前者は全件を取り出してから捨てますが、後者は必要なものだけを取り出します。10 万件あるうちの 10 件がほしいとき、この差は大きくなります。
並べ替えも同じです。ORDER BY price と書けば、データベースが並べて返します。
取り出す列を選ぶ
第3章から「返すものは選ぶ」と書いてきました。SQL では取り出す段階で選べます。
JavaScript
db.prepare("SELECT id, name, price FROM items").all();SELECT * は全部の列を持ってくる書き方です。楽ですが、ownerEmail のような外に出したくない列まで手元に来ます。必要な列だけを書くほうが、うっかり返してしまう事故を防げます。
1件と一覧で使い分ける
JavaScript
app.get("/items", (req, res) => {
res.json(db.prepare("SELECT id, name, price FROM items").all());
});
app.get("/items/:id", (req, res) => {
const item = db.prepare("SELECT id, name, price FROM items WHERE id = ?").get(Number(req.params.id));
if (!item) {
return res.status(404).json({ error: "商品が見つかりません" });
}
res.json(item);
});all は空でも配列、get は無ければ undefined です。第4章で決めた「一覧は空配列で 200、1 件は 404」に、そのまま重なります。
手を動かす
演習では、一覧と詳細をデータベース読みに置き換えます。絞り込みは SQL に任せてください。
要件
GET /itemsはSELECTで一覧を返し、minPriceがあればWHERE price >= ?で絞るGET /items/:idは 1 件を返し、無ければ 404 で{"error":"商品が見つかりません"}- 取り出す列は
idnamepriceだけにする
入出力例
request("GET", "/items") → "200 [{"id":1,"name":"レザースニーカー","price":4800},{"id":2,"name":"ランニングスニーカー","price":3200},{"id":3,"name":"古着のデニムジャケット","price":6200}]"
request("GET", "/items?minPrice=4000") → "200 [{"id":1,"name":"レザースニーカー","price":4800},{"id":3,"name":"古着のデニムジャケット","price":6200}]"
request("GET", "/items?minPrice=99999") → "200 []"
request("GET", "/items/2") → "200 {"id":2,"name":"ランニングスニーカー","price":3200}"
request("GET", "/items/999") → "404 {"error":"商品が見つかりません"}"ヒント
編集 ゆめさく編集部