1. 既定は先頭から2件
  2. 安い順に2件
  3. 安い順の3件目から2件。先に切り出すと結果が変わる
  4. limit を増やせば全件
  5. 並べ替えても元の並びは壊れない
コース一覧
Express道場 fleama開発室のIssue10件
#104 検索に並び替えとページングを

Express道場 fleama開発室のIssue10件

Node.js入門で作り上げた fleama API の開発室に、スプリントの助っ人として参加する演習専用コースです。解説はありません。1問が1件の Issue で、報告者は商店街の住人たち。依頼と完成条件だけを読み、白紙から自分で組み立てます。手が止まったときのために、方針・使う構文・部分解の3段階のヒントを各問に用意しています。ヘルスチェックから始まり、一覧API、404の扱い、並び替えとページング、入力検証、自作ミドルウェア、エラー形式の統一、所有者チェック、二重販売を止めるトランザクションを経て、最後はいいね機能をエンドポイント設計から任されるところまで、10件の Issue で Express の主要な道具を一巡します。1問15分から45分、全10問で約5時間です。Node.js入門を終えて「作れたけれど実務で通用するか不安」と感じている方に向いています。

1
今週のスプリント
01. #101 監視用ヘルスチェックが欲しい15分
02. #102 カテゴリ一覧APIが欲しい20分
03. #103 消えた商品を開くと落ちる20分
04. #104 検索に並び替えとページングを25分
05. #105 0円出品が通ってしまう25分
06. #106 調査用のアクセスログを25分
07. #107 エラーの形式がバラバラ30分
08. #108 他人の出品を値下げできてしまう30分
09. #109 同じ商品が2人に売れた35分
10. #110 新機能「いいね」を設計から45分

#104 検索に並び替えとページングを

中段 / 目安 25分


Issue #104 検索に並び替えとページングを

報告者: 栞(司書・文庫の除籍本を出品中)

「本を安い順に、少しずつ見たいんです。全部いっぺんに出ると、目が回ってしまって」


一覧に付ける機能としては定番の2つです。どちらもクエリで受け取ります。

プレーンテキスト

/items?sort=price&limit=2&offset=0

ここで必ず踏む落とし穴が2つあります。

1つ目は型です。 クエリの値はすべて文字列で届きます。

JavaScript

const limit = req.query.limit; // "2" const limit2 = Number(req.query.limit); // 2

"2" のまま slice に渡すと、意図しない切り出しになります。数として使うなら必ず直してください。

2つ目は順番です。 処理には正しい順序があります。

プレーンテキスト

並べ替える → 切り出す

先に切り出してから並べ替えると、その2件の中だけで並ぶので、全体で見た安い順にはなりません。範囲を狭めるのは最後です。

もう1つ、sort は元の配列を書き換えます。写しを作ってから並べ替えてください。

JavaScript

const sorted = [...items].sort((a, b) => a.price - b.price);

完成条件

GET /items に、並び替えとページングを足してください。

  • sort=price なら価格の安い順にする。指定が無ければ元の並びのまま
  • limit は返す件数(既定は 2)
  • offset は飛ばす件数(既定は 0)

処理は並べ替えてから切り出す順です。元の items を壊さないようにしてください。

要件

  1. sort=price で価格の安い順に並べ替える(元の配列は壊さない)
  2. limit(既定 2)と offset(既定 0)で切り出す
  3. 処理は 並べ替える → 切り出す の順にする

入出力例

request("GET", "/items") → "200 [{"id":1,"name":"レザースニーカー","price":4800},{"id":2,"name":"文庫本セット","price":900}]" request("GET", "/items?sort=price") → "200 [{"id":2,"name":"文庫本セット","price":900},{"id":4,"name":"木製のスツール","price":3500}]" request("GET", "/items?sort=price&limit=2&offset=2") → "200 [{"id":1,"name":"レザースニーカー","price":4800},{"id":3,"name":"古着のデニムジャケット","price":6200}]" request("GET", "/items?limit=10") → "200 [{"id":1,"name":"レザースニーカー","price":4800},{"id":2,"name":"文庫本セット","price":900},{"id":3,"name":"古着のデニムジャケット","price":6200},{"id":4,"name":"木製のスツール","price":3500}]" request("GET", "/items?limit=4") → "200 [{"id":1,"name":"レザースニーカー","price":4800},{"id":2,"name":"文庫本セット","price":900},{"id":3,"name":"古着のデニムジャケット","price":6200},{"id":4,"name":"木製のスツール","price":3500}]"

ヒント

前のヒントを開くと次が開きます。開かずに解けると未開封クリアです

まず `[...items]` で写しを作ります。ここを飛ばすと元の並びが壊れます

ヒント 2ヒント 1 を開くと読めます
ヒント 3ヒント 2 を開くと読めます
生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/08/10

関連レッスン

  • #105 0円出品が通ってしまう

    タイトル必須と価格の下限を確かめ、不正な出品を400で止めます。

  • #106 調査用のアクセスログを

    全リクエストのメソッドとパスを記録するミドルウェアを自作します。

  • #107 エラーの形式がバラバラ

    バラバラだったエラー応答を、共通ハンドラで1つの形に統一します。

  • #108 他人の出品を値下げできてしまう

    出品者だけが値下げできるよう、401と403を使い分けて守ります。

main.js
学習モード
エディタを読み込んでいます

メモ

#104 検索に並び替えとページングを

⌘S で保存