コンテンツにスキップ

データベース概要

前提

項目 内容
DBMS PostgreSQL 17
ORM Drizzle ORM
スキーマ定義 src/db/schema.ts(単一ファイルが唯一の定義元)
開発時の反映 bun run db:push(スキーマを DB に直接反映)
マイグレーション bun run db:generate でファイル生成、scripts/migrate.ts が本番で実行
GUI bun run db:studio(Drizzle Studio)

命名は snake_case、テーブル名は複数形。主キーはすべて serial(integer の auto-increment)。日時は timestamp(タイムゾーンなし)。

論理削除は使わない

deleted_at による論理削除は採用していない。削除は物理削除で、外部キーの onDelete: cascade によって関連レコードも消える。予約のみ、キャンセルを status = 'cancelled' で表現する。

ER 図

erDiagram
  users ||--o{ projects : "created_by"
  users ||--o{ project_interviewers : "user_id"
  users ||--o{ reservations : "interviewer_id"
  users ||--o{ candidate_available_dates : "interviewer_id"
  projects ||--o{ project_candidates : "project_id"
  projects ||--o{ project_interviewers : "project_id"
  projects ||--o{ email_templates : "project_id"
  projects ||--o{ import_logs : "project_id"
  candidates ||--o{ project_candidates : "candidate_id"
  project_candidates ||--o| reservations : "project_candidate_id"
  project_candidates ||--o{ scheduling_tokens : "project_candidate_id"
  project_candidates ||--o{ candidate_available_dates : "project_candidate_id"
  project_candidates ||--o{ email_logs : "project_candidate_id"
  project_candidates ||--o{ status_histories : "project_candidate_id"
  email_templates ||--o{ email_logs : "template_id"

調査メタキャッシュ(databricks_surveys)は上記のいずれとも外部キーで結ばれていない。回答本体は Postgres に持たず、Databricks から直接読む(Databricks 連携)。

テーブル一覧

テーブル 論理名 分類 ページ
users ユーザー コア コア
projects プロジェクト コア コア
candidates 候補者 コア コア
project_candidates プロジェクト候補者 コア コア
project_interviewers プロジェクト面接官 コア コア
scheduling_tokens 調整トークン 日程調整 日程調整
candidate_available_dates 候補者希望日程 日程調整 日程調整
reservations 予約 日程調整 日程調整
status_histories ステータス履歴 日程調整 日程調整
email_templates メールテンプレート メール メール
email_logs メール送信ログ メール メール
import_logs インポートログ インポート インポート・調査メタキャッシュ
databricks_surveys 調査メタ インポート インポート・調査メタキャッシュ

enum 一覧

enum 名 値 使用箇所
user_role admin / member / viewer users.role
project_status draft / active / completed / archived projects.status
interview_type online_meet / online_zoom / offline / any projects.interview_type
selection_type primary / reserve project_candidates.selection_type
pc_status not_contacted / contacted / waiting_response / scheduling / scheduled / interviewed / completed / declined / bounced / cancelled project_candidates.status
template_type invitation / reminder / confirmation / cancellation email_templates.type
email_status sent / delivered / bounced / failed email_logs.status
reservation_interview_type online_meet / online_zoom / offline reservations.interview_type
reservation_status confirmed / cancelled reservations.status
import_type manual_tsv / manual_survey / auto_survey import_logs.import_type
import_status pending / processing / completed / partial / failed import_logs.status

interview_type は 2 種類ある

プロジェクトは「指定なし」を許すため any を持つが、確定した予約は形式が決まっているため reservation_interview_type には any がない。

JSON カラム

構造を持つ JSON カラムは、型が src/db/schema.ts または src/types/survey-import.ts に定義されている。

テーブル.カラム 型 内容
projects.scoring_rules ScoringRules スコアリングルールの配列と上限点
projects.survey_import_mapping ImportMapping アンケート回答からのフィールドマッピング
projects.survey_import_filter ImportFilter アンケートインポート時の絞り込み条件
projects.arrange_settings ArrangeSettings アレンジフロー STEP1〜3 の設定
project_candidates.attributes Record<string, unknown> 候補者属性(jsonb)
project_candidates.survey_responses Record<string, unknown> アンケート回答(jsonb)
import_logs.error_details ImportError[] インポートエラーの明細
import_logs.payload Record<string, unknown> インポート実行時のリクエスト内容

arrange_settings の型は二重定義

backend の src/db/schema.ts と frontend の src/types/arrange-settings.ts の両方に定義がある。片方を変えたらもう片方も直す。

インデックス方針

  • 一覧の絞り込みに使う列に複合インデックスを張る(idx_pc_project_status / idx_res_interviewer_scheduled など)
  • 一意性制約は unique() で明示する(uk_project_candidate / uk_project_user)
  • 調査メタキャッシュは更新日時(synced_at)にインデックスを持つ