Zettelkasten Inbox / ブロック詳細
知識の木を丸ごと俯瞰する読み取り専用の画面。本題は「関連づけでは繋がっているのに、本文からは1度も引かれていないノート」を、本文を再帰的にたどって炙り出すこと。
抽象度 Lv.4(技術用語+システム上のやりとりまで/製品名・ライブラリ名は書かない)受信箱が「これから処理する1件」を見る画面なのに対して、こちらは Tag → ABC Note → Literature Note という知識の木を、丸ごと1画面で俯瞰する読み取り専用の画面。
ただ一覧するだけではない。このブロックの本題は 「関連づけとしては繋がっているのに、本文からは1度も引かれていないノート」を探し出すことにある。 アプリではこれを「サブ埋没」と呼んでいる。
Notionのプロパティ(関連づけ)を見るだけの他のブロックと違い、 ここだけはABC Noteの本文の中身を再帰的にたどって調べる。 このアプリで最も種類の違う処理が入っている場所である。
1. アクセス確認 → 10. 全体マップと「サブ埋没」判定 → 2番(修正モードで受信箱へ戻る)
/?note=◯◯ という形で受信箱へ渡すGET /api/map と POST /api/map/sub-buriedno-store でブラウザには保存させない受信箱と対になる画面。受信箱は「まだ何もしていないノート」だけを見せる。 だから一度処理したノートは、受信箱からは二度と見えない。 処理したあとで「Tagが違った」「本文に書き足し忘れた」と気付いたときに、 もう一度その1件へ戻る唯一の入口が、この全体マップになっている。
「サブ埋没」という考え方が、このアプリの思想を一番よく表している。 Notionの関連づけを付ければ、見た目のうえでは繋がる。だが ABC Noteの本文で引用していなければ、その知識は使われていない。 関連づけは繋がりの宣言にすぎず、本文への引用が繋がりの実体である―― という区別を、機械的に検出する仕組みにしている。
2段階の「埋没」がある。 埋没=Tagは付いているがABC Noteに1つも繋がっていないノート。 サブ埋没=ABC Noteには繋がっているが、その本文からは引かれていないノート。 前者は関連づけを見るだけで分かるので 10-4 で出るが、後者は本文を読まないと分からないので別のAPIになっている。
3件ずつに分けている理由。1件の判定でNotionへ何十往復もしうるので、 全部まとめて投げると1回の要求が長くなりすぎる。 小分けにして進み具合を画面に出しながら少しずつ進める形にしている。
| 工程 | 主体 | やりとりの内容 | 方向 |
|---|---|---|---|
| 10-1 | ブラウザ → マップAPI | 全体マップの要求 | → |
| 10-2 | マップAPI → Notion | 3つのDBを同時に全件取得 | → |
| 10-3 | マップAPI → Notion | 100件を超える関連だけ追加で取得 | → |
| 10-4 | マップAPI(内部) | 木の組み立てと13種類の集計 | ↻ |
| 10-5 | マップAPI → ブラウザ | Tag・ABC・Literatureの木と集計 | ← |
| 10-6 | ブラウザ → サブ埋没API | ABC NoteのID(1回3件まで) | → |
| 10-7 | サブ埋没API → Notion | 本文を入れ子の奥まで再帰的に取得 | → |
| 10-8 | サブ埋没API(内部) | ブロックのJSONからIDを探す | ↻ |
| 10-9 | サブ埋没API → ブラウザ | 本文から引かれている/いないの2配列 | ← |
| 10-10 | ブラウザ(内部) | 修正が必要なノートを受信箱へ渡す | ↻ |
10-1 全体マップの画面を開くと、木のデータを丸ごと1回で問い合わせる。
技術的には GET /api/map、
Cache-Control: no-store。絞り込みの指定は無い。
画面側の検索・折りたたみ・「空のTagを隠す」といった操作は
すべて受け取ったデータに対してブラウザの中で行うので、
このAPIを呼ぶのは画面を開いたときの1回だけ。
10-2 Notionの3つのデータベースを、同時に全部取りに行く。
技術的には Tag DB・ABC DB・Literature DB の3つの全件取得を 同時に投げて、3つとも揃うのを待つ。 2番の受信箱の初期読込がまったく同じ3つを1つずつ順番に取っているのに対し、 こちらは並行。同じアプリの中で判断が分かれている。 なおLiterature DBには絞り込みが無いので、処理済みも未処理も含めた全件が対象になる。 2番が「両方空」で絞っていたのとは規模が桁違いで、ここがこの画面の重さの原因。
10-3 Literature Noteを1件ずつ見て、関連づけが多すぎて 一度に返ってこなかったものだけ、追加で取りに行く。
技術的には ページ取得の応答には関連が最大25件しか入らず、 「まだ続きがある」印だけが立つ。その印が立っているものだけ、 専用の問い合わせで100件ずつ取り切る。 印が立っていなければ追加の通信は起きないので、 普通のノート(関連が数件)では往復ゼロ。 ただしこのループは1件ずつ順番に回るので、 関連の多いノートが何件もあると、その分だけ直列に時間が積み上がる。
10-4 取ってきた3つを組み合わせて木を作り、数を数える。 どこにも収まらないものは「要確認」として別枠に出す。
技術的には 組み立ての規則が3つ。 (1) ABC Noteの配置:親Tagがちょうど1つで、そのTagが実在すればその下へ。 親Tagが0個・2個以上・存在しないTagを指す、のいずれかなら「要確認」の別枠。 6番の候補絞り込みと同じ条件なので、ここに出るABC Noteは受信箱の候補には永久に出てこない。 (2) 埋没の判定:ABC Noteへの関連が1つも無いLiterature Noteを、 付いているTagごとに集める。これが「Tagは付けたが、どの知識にも組み込まれていない」ノート。 (3) 集計:13種類。Tag数、ABC Noteを持つTagの数、ABC総数、 Literature総数、Tag付き/Tagなし、Tag付きでABCあり/Tag付きでABCなし、 引用されているLiteratureの数、関連の総本数、埋没の数、埋没の関連本数、要確認のABC数。 並び順は埋没が多いTagが上――「片付いていないところ」から目に入るようにしてある。
10-5 木と集計を返す。5分間は同じものを使い回す。
技術的には 200 + no-store。
サーバー側の控えは5分。2番の30秒より長いのは、
この画面が「いま処理する1件」ではなく「全体の傾向」を見るものだから。
保存・削除・Tag作成が起きれば、時間に関係なく即座に捨てられる。
10-6 木が届いたら、画面はすぐに次の分析を始める。 引用されているノートを持つABC Noteを、3件ずつ順番に調べていく。
技術的には POST /api/map/sub-buried に
{"abcIds": [...]}。1回1〜3件で、それ以外は 400。
3件の束を順番に投げ、1つ終わるごとに進み具合(何件中何件)を画面に出す。
Literature Noteが1件も繋がっていないABC Noteは、調べる意味が無いので最初から除外する。
画面を離れたり再読み込みしたりすると、途中で取り消される。
10-7 ABC Noteの本文を、上から順に、折りたたみの中まで潜って読んでいく。
技術的には ここがこのアプリで唯一の 再帰的な探索。ブロックを100件ずつ取り、 「子を持つ」印が立っているブロックがあれば、その中へ降りて同じことを繰り返す。 3番の本文取得が直下しか見ないのと正反対で、 トグルの中でも表の中でも、どこに書かれていても見つける。 暴走を防ぐ歯止めが2つ。 (1) 同じブロックは1度しか降りない(訪問済みを記録する)。 (2) 5,000ブロックで打ち切る。 さらに探しているIDが全部見つかった時点で、途中でも打ち切る―― これが効いていて、本文の冒頭でリンクを並べているABC Noteなら、 最初の100件を読んだ時点で終わる。
10-8 ブロック1つ1つについて、その中身のどこかに 対象ノートの番号が書かれていないかを探す。
技術的には やり方が大胆で、 ブロックの構造を解析せず、中の文字列という文字列を全部さらって、 32桁の16進またはハイフン付きのIDに一致するものを集める。 配列でも入れ子の物でも、再帰的に降りて文字列だけを拾う。 メンション(ページの埋め込みリンク)でも、 本文中に貼ったNotionのURLでも、どちらでも見つかるのが利点。 「メンションだけを探す」実装にすると、URLを直接貼った引用を見落とすため。 比較の前にハイフンを外して小文字に揃えるので、表記の違いに左右されない。 結果は「本文から引かれているノート」と「引かれていないノート」の2つの配列になる。
10-9 判定結果を返す。30分は同じ結果を使い回す。
技術的には 控えの鍵が2つの組み合わせになっている。 そのABC Noteの最終更新時刻と、 繋がっているLiterature NoteのIDを並べ替えて連結した文字列。 本文を直しても、関連を1つ足しても、鍵が変わって控えが無効になる。 30分という長さを許せるのは、この鍵があるから。 画面側は届いた結果を集計に反映し、「本文から引かれている◯件/サブ埋没◯件」を出す。
10-10 直したいノートが見つかったら、その場から受信箱へ飛べる。 飛んだ先では、既存のTagとABC Noteが「維持」と表示されて外せなくなる。
技術的には /?note=◯◯ というURLで受信箱を開くと、
2番が修正モードで動き、そのノートの現在の関連を全部たどって画面に渡す。
受信箱側は既存のTag・ABCを「維持」の印付きで押せない状態にする。
保存すると 8番が「開いた時点と変わっていないか」と「1つも外していないか」を確かめ、
成功したら受信箱に留まらず全体マップへ戻る。
この往復が、2つの画面をつなぐ唯一の道。
← 図は横にスクロールできます
400 +
「ABC Noteは1回につき1〜3件を指定してください。」400 +
「ABC DBにないノートが含まれています。画面を更新してください。」※ 2026年8月14〜15日時点の zettelkasten-inbox のプログラムを読んで作成しました。過去の設計資料は参照していません。
※ 番号は全体図・この解説・シーケンス図で共通です。工程番号は「ブロック番号-連番」で書いています。