1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude CodeでFirestore設計を失敗しない手順|クエリから逆算するスキーマ設計

1
Posted at

Claude CodeでFirestore設計を失敗しない手順

Firestoreは「コレクションをどう分けるか」から考えると失敗しがちです。

自分も最初は users / posts / comments のようにRDBっぽく考えていました。でも実際には、「公開記事を新着順で出す」「著者ごとの記事を出す」「下書きだけ管理画面に出す」といったクエリのほうが先にあります。

この記事では、Claude Codeを使ってFirestore設計をクエリから逆算する手順をまとめます。

1. まず画面からクエリ一覧を作る

claude -p "
メディアCMSのFirestore設計をしたい。
まずコレクションを作らず、画面ごとに必要なクエリ一覧を作ってください。
where / orderBy / limit / 必要な複合インデックスも表にしてください。
"

例:

画面 where orderBy インデックス
記事一覧 status == published publishedAt desc status, publishedAt
著者ページ authorId, status publishedAt desc authorId, status, publishedAt
管理画面 status == draft updatedAt desc status, updatedAt

2. 一覧用の小さな情報は非正規化する

export interface PostDoc {
  id: string;
  slug: string;
  title: string;
  status: "draft" | "published" | "archived";
  lang: "ja" | "en" | "es" | "ko";
  authorId: string;
  authorName: string;
  tagSlugs: string[];
  tagNames: string[];
  publishedAt: FirebaseFirestore.Timestamp | null;
  updatedAt: FirebaseFirestore.Timestamp;
}

authorName や tagNames は重複ですが、一覧表示で追加読み取りを減らせます。

3. Zodで保存前に検証する

import { z } from "zod";

export const CreatePostSchema = z.object({
  slug: z.string().min(3).max(120).regex(/^[a-z0-9-]+$/),
  title: z.string().min(1).max(120),
  lang: z.enum(["ja", "en", "es", "ko"]),
  authorId: z.string().min(1),
  authorName: z.string().min(1),
  tagSlugs: z.array(z.string()).max(8),
  tagNames: z.array(z.string()).max(8),
});

4. インデックスはGit管理する

{
  "indexes": [
    {
      "collectionGroup": "posts",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "lang", "order": "ASCENDING" },
        { "fieldPath": "status", "order": "ASCENDING" },
        { "fieldPath": "publishedAt", "order": "DESCENDING" }
      ]
    }
  ]
}

5. セキュリティルールも同時に考える

match /posts/{postId} {
  allow read: if resource.data.status == "published" || isAdmin();
  allow create, update, delete: if isAdmin();
}

Firestoreは柔軟ですが、自由に設計してよいわけではありません。

ポイントは、クエリ・インデックス・料金・セキュリティルールを同時に見ることです。

詳しいコードと設計の考え方はブログ版にまとめています。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?