検索
一言でいうと
search は backend 専用モジュールで、frontend に対応する app/modules/search/ は存在しない。ドキュメント・レコードを横断する 全文検索(Postgres の tsvector ベース、同期的・即時)と セマンティック検索(pgvector + HNSW インデックスによるベクトル類似検索、非同期・週次バッチ)の2系統を提供し、frontend 側はヘッダー検索やAI エージェントの MCP tool から都度呼び出すクライアントの立場になる。
主要ドメイン概念
| 概念 | 役割 |
|---|---|
全文検索(FullTextSearchPort) | ドキュメント/レコードのタイトル・本文を tsvector で検索。書き込み直後から検索可能(非同期インデックス待ちなし) |
DocumentEmbedding | ドキュメントのベクトル埋め込み(1536→768次元に移行済み、vector 型カラム + HNSW cosine インデックス) |
EmbeddingIndexQueueEntry | セマンティック検索インデックスの待ち行列エントリ。ドキュメント作成/本文変更イベントで INSERT ... ON CONFLICT DO NOTHING されるだけの軽量エンキュー |
SearchHitResponse | 検索結果1件(entityType でドキュメント/レコード等を判別) |
Backend 構造
api/controller/:SearchController(POST /api/v1/search— 認証済みユーザー向け全文+セマンティック検索)、SearchPublicController/SearchFileUploadPublicController(公開デモ用の検索・ファイルアップロード API)、EmbeddingController(POST /reindex・/reindex/workspace・/reindex/folder— 管理者向け手動再インデックス)domain/service/:SearchService(FullTextSearchPortを各エンティティソースに委譲し、結果をデデュープ・権限フィルタしてマージする)、SemanticSearchService(ベクトル類似検索)、DocumentEmbeddingService/EmbeddingIndexingService(埋め込み生成・キュー処理)domain/model/:DocumentEmbedding・EmbeddingIndexQueueEntry・SearchModelsdomain/port/:FullTextSearchPortinfrastructure/listener/:DocumentCreatedEnqueueListener(DocumentNodeChangedEventの CREATED/CONTENT_CHANGED を購読し、親ワークスペースのsemantic_search_enabledが真ならエンキューするだけ。LLM 呼び出しはしない)infrastructure/scheduler/:EmbeddingQueueWorker(既定は週次 cron でキューを消化し実際に埋め込みを生成。BudgetEnforcerでテナントごとのAI予算に従う)、DemoSearchCleanupScheduler
Frontend からの呼び出し元
frontend 専用モジュールはなく、以下のように各所から POST /api/v1/search を直接叩く。
foundation/composables/navigation/useHeaderSearch.ts→layouts/components/header/HeaderSearch.vue(ヘッダーのグローバル検索。searchContent(本文全文検索)はデフォルトOFFで、ONにするとRECORDタイプのヒットが有効になる)- AI エージェント側は MCP tool 経由で検索を呼ぶ(
core/mcp/infrastructure/tools/SearchMcpTools.kt・SemanticSearchMcpTools.kt)— チャット中の「〜を探して」に相当する操作はここを通る
他モジュールとの辺
editor:DocumentCreatedEnqueueListenerがドキュメントツリーの変更イベントを購読し、セマンティック検索インデックスをエンキューするai: セマンティック検索の埋め込み生成にはBudgetEnforcer(AI予算管理)が絡み、MCP tool 経由でAIエージェントから呼ばれるworkspace: セマンティック検索はワークスペース単位の opt-in(semantic_search_enabled)
セマンティック検索は「ドキュメントを作ったら即座に検索できる」わけではない。全文検索は書き込み直後から効くが、セマンティック検索は (1) ワークスペースで opt-in されていない限り一切エンキューされず、(2) エンキューされても既定では 週次 cron(EmbeddingQueueWorker)まで実際の埋め込み生成が走らない。「セマンティック検索でヒットしない」という報告を見たら、まず opt-in 設定とキュー処理のタイミングを疑うこと(即時反映を期待する設計ミスは禁止— 手動再インデックスは EmbeddingController の /reindex 系エンドポイントで可能)。