検索・バルク・ビュー・添付 仕様書
ステータス: Draft / 作成日: 2026-05-27 PR #7 — 依存: コア、ファイル添付は Drive機能 も必要
1. 全文検索
データモデル
tasks テーブルに tsvector カラムを追加(Generated Column)。
前提: PostgreSQL 標準の
tsvectorは日本語辞書を内包しない。pg_bigm拡張(バイグラム分割)または PGroonga をサーバーに導入した上で使用する。本仕様ではpg_bigmを採用し、辞書名はpg_catalog.simpleではなくpublic.pg_bigmを使用する(§7 未決事項も参照)。
-- pg_bigm 拡張を有効化(スーパーユーザー権限が必要)
CREATE EXTENSION IF NOT EXISTS pg_bigm;
ALTER TABLE tasks
ADD COLUMN search_vector tsvector
GENERATED ALWAYS AS (
to_tsvector('pg_catalog.simple',
coalesce(title, '') || ' ' || coalesce(description, ''))
) STORED;
CREATE INDEX idx_tasks_search ON tasks USING GIN(search_vector gin_bigm_ops);
コメント全文も検索する場合は task_comments.body を別途検索してタスク ID でマージする。
API
GET /tasks/search?q=OAuth&limit=20&offset=0
レスポンス(スコア降順):
{
"tasks": [
{
"id": "uuid", "seq_id": 42,
"title": "OAuth 対応を実装する",
"highlight": "…<em>OAuth</em> Apps を使って…",
"score": 0.92
}
],
"total": 5
}
PostgreSQL の
ts_headlineで検索語をハイライト表示。'japanese'辞書はpg_bigm等の拡張が必要な場合は未決事項(後述)。
2. バルク操作
API
POST /tasks/bulk
リクエスト:
{
"task_ids": ["uuid1", "uuid2", "uuid3"],
"operations": [
{ "type": "set_status", "status_id": "uuid" },
{ "type": "add_label", "label_id": "uuid" },
{ "type": "set_sprint", "sprint_id": "uuid" }
]
}
対応する type:
レスポンス:
{
"updated": 3,
"failed": []
}
3. 保存済みビュー
データモデル
pub struct SavedView {
pub id: Uuid,
pub project_id: Uuid,
pub created_by: Uuid,
pub name: String,
pub is_shared: bool,
pub filters: Value, // JSON
pub sort: Value,
pub view_type: String, // board | list | table
pub created_at: DateTimeUtc,
}
filters JSONB スキーマ:
{
"status_ids": ["uuid"],
"priority": ["high", "critical"],
"assignee_ids": ["uuid"],
"label_ids": ["uuid"],
"sprint_id": "uuid",
"milestone_id": "uuid",
"deadline_before": "2026-07-01",
"is_archived": false,
"has_no_assignee": false
}
マイグレーション
CREATE TABLE saved_views (
id UUID PRIMARY KEY,
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
created_by UUID NOT NULL REFERENCES users(id),
name VARCHAR(100) NOT NULL,
is_shared BOOLEAN NOT NULL DEFAULT false,
filters JSONB NOT NULL DEFAULT '{}',
sort JSONB NOT NULL DEFAULT '{}',
view_type VARCHAR NOT NULL DEFAULT 'list',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
API
GET /tasks に ?view_id=uuid を渡すと保存済みフィルターを適用。
4. ファイル添付
Drive の drive_files をタスクへ紐付ける中間テーブル。
データモデル
マイグレーション
CREATE TABLE task_attachments (
task_id UUID NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
drive_file_id UUID NOT NULL REFERENCES drive_files(id) ON DELETE CASCADE,
attached_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (task_id, drive_file_id)
);
API
POST リクエスト(先に Drive API でアップロードして drive_file_id を取得する):
{ "drive_file_id": "uuid" }
レスポンスには MIME タイプ・コンテンツ URL を含める。フロントエンドが MIME タイプを見て表示を出し分ける。
プレビュー生成の方針:
動画サムネイルをまともに生成するには
ffprobe/ffmpegのサーバーへのインストールが必要。Phase A では動画は再生リンクのみ提供し、サムネイル生成は Phase B の追加タスクとして扱う。
5. マイタスク API
プロジェクト横断で自分担当のタスクを返す。
GET /v1/users/me/tasks?status=open&priority=high&limit=50
レスポンス: タスク一覧(project フィールドを含む)
6. フロントエンド(Phase B)
検索 UI
グローバルサーチ(Cmd+K / Ctrl+K)でタスクを横断検索。ハイライト付きで表示。
バルク操作 UI
タスク一覧でチェックボックスを選択 → ツールバーが出現 → ステータス・ラベル等を一括変更。
保存済みビュー UI
左サイドバーに一覧表示。現在のフィルター条件から「ビューとして保存」ができる。