[{"data":1,"prerenderedAt":424},["ShallowReactive",2],{"content-/turso-book-db-migration":3,"all-pages-for-dir":422,"og-image-/turso-book-db-migration":423},{"id":4,"title":5,"body":6,"category":401,"description":402,"extension":403,"meta":404,"navigation":405,"ogImage":406,"path":407,"project_name":408,"published":409,"publishedAt":410,"seo":411,"stem":412,"tags":413,"todo":420,"unpublished":409,"updatedAt":406,"__hash__":421},"pages/2026-04/2026-04-11/turso-book-db-migration.md","Turso Embedded Replicaで書籍DBを移行 - OCRデータ格納からdev確認まで",{"type":7,"value":8,"toc":381},"minimark",[9,14,18,21,26,34,37,39,42,49,55,72,76,79,81,85,90,128,131,133,137,141,144,158,161,165,168,171,173,177,180,184,187,191,194,198,201,244,247,250,270,273,275,278,302,304,307,377],[10,11,13],"h1",{"id":12},"turso-embedded-replicaで書籍dbを移行した","Turso Embedded Replicaで書籍DBを移行した",[15,16,17],"p",{},"edinet-apiリポジトリのドキュメント整理から始まって、book-knowledge-baseのTurso移行を一気に進めた。税法入門のPDF 107ページをOCRにかけ、Turso DBに流し込み、devサーバーで書籍一覧が表示されるところまで持っていった。ポート番号の衝突で3回やり直す羽目になったが、最終的にページナビゲーションもコンテンツ表示も動いている。",[19,20],"hr",{},[22,23,25],"h2",{"id":24},"embedded-replicaのドキュメント整理","Embedded Replicaのドキュメント整理",[15,27,28,29,33],{},"edinet-apiリポジトリに ",[30,31,32],"code",{},"turso-embedded-replica-windows-guide.md"," を作成した。前日までの試行錯誤で得た知見を整理する目的。Windows環境でのlibsqlパッケージ選定、接続コード、sync周りの挙動をまとめた。",[15,35,36],{},"これを書いている途中で、レプリカディレクトリの配置が気になり始めた。",[19,38],{},[22,40,41],{"id":41},"レプリカディレクトリの配置見直し",[15,43,44,45,48],{},"当初は ",[30,46,47],{},"~/.turso-replicas/"," にレプリカDBファイルを置いていた。ホームディレクトリ直下のドットディレクトリ。設定ファイルと同じ感覚で置いたが、実際にはDBファイルは数十MBのデータであって設定ではない。",[15,50,51,54],{},[30,52,53],{},"Git_repo/turso-replicas/"," に移した。理由は2つ:",[56,57,58,66],"ol",{},[59,60,61,65],"li",{},[62,63,64],"strong",{},"開発リポジトリ群と同じ階層に置く",": 他のリポジトリからの相対パスが予測しやすい",[59,67,68,71],{},[62,69,70],{},"バックアップの対象に含めやすい",": Git_repo配下なら既存のバックアップフローに乗る",[73,74,75],"h3",{"id":75},"サイズ確認",[15,77,78],{},"ローカルSQLiteのサイズを確認した。16冊分のOCRデータを含めて約20MB。Turso無料枠は5GB。余裕がある。当面はコスト面を気にせず使える。",[19,80],{},[22,82,84],{"id":83},"turso-replicas-リポジトリの初期化","turso-replicas リポジトリの初期化",[15,86,87,89],{},[30,88,53],{}," を新規リポジトリとして初期化し、以下のファイルを作成した:",[91,92,93,101,116,122],"ul",{},[59,94,95,100],{},[62,96,97],{},[30,98,99],{},".env",": Turso URLとAuth Tokenの定義",[59,102,103,108,109,111,112,115],{},[62,104,105],{},[30,106,107],{},".gitignore",": ",[30,110,99],{}," と ",[30,113,114],{},"*.db"," をトラッキング対象外に",[59,117,118,121],{},[62,119,120],{},"FTS5検証スクリプト",": libsql経由でFTS5テーブルを作成し、全文検索が動くか確認するPythonスクリプト",[59,123,124,127],{},[62,125,126],{},"計画書",": 移行手順のステップを箇条書きで整理",[15,129,130],{},"FTS5検証スクリプトを回して、Turso上でも全文検索が問題なく動くことを確認した。前日のCodexレビューで「FTS5の互換性が未検証」と指摘されていた点を潰した形になる。",[19,132],{},[22,134,136],{"id":135},"税法入門のocrとdb格納","税法入門のOCRとDB格納",[73,138,140],{"id":139},"pdfのリネームとocr","PDFのリネームとOCR",[15,142,143],{},"「税法入門 令和8年度版」のPDFをリネームしてからyomitoku OCRにかけた。",[91,145,146,152],{},[59,147,148,151],{},[62,149,150],{},"107ページ",": テキスト抽出",[59,153,154,157],{},[62,155,156],{},"14図ファイル",": 図表の画像を個別に切り出し",[15,159,160],{},"yomitokuの処理自体は安定していた。107ページを通しで回して、途中でエラー落ちすることなく完走した。",[73,162,164],{"id":163},"turso-dbへの格納","Turso DBへの格納",[15,166,167],{},"OCR結果をパースして、ページ単位でTurso DBにINSERTした。書籍メタデータ（タイトル、著者、ページ数）と、各ページのテキストコンテンツを別テーブルに分けている。",[15,169,170],{},"格納完了後、FTS5インデックスの再構築を走らせた。「所得税」で検索すると該当ページがヒットすることを確認。",[19,172],{},[22,174,176],{"id":175},"chrome-devtoolsでのdev表示確認","Chrome DevToolsでのdev表示確認",[15,178,179],{},"ここからが一番手間取った。book-knowledge-baseのdevサーバーを起動してChrome DevTools MCPで表示を確認しようとしたが、ポート番号で3回転んだ。",[73,181,183],{"id":182},"ポート3000-既に使用中","ポート3000: 既に使用中",[15,185,186],{},"Nuxtのデフォルトポート3000でdevサーバーを起動しようとしたら、既に別のプロジェクト（mdx-playground）が使っていた。エラーメッセージを見て即座にポートを変更。",[73,188,190],{"id":189},"ポート3001-これも塞がっていた","ポート3001: これも塞がっていた",[15,192,193],{},"3001に切り替えて起動。今度は起動自体は通ったが、Chrome DevToolsで接続しようとするとタイムアウトした。調べると別プロセスが3001を掴んでいた。",[73,195,197],{"id":196},"ポート3003-ようやく通った","ポート3003: ようやく通った",[15,199,200],{},"3003まで飛ばしてようやくdevサーバーが起動し、Chrome DevToolsからの接続も通った。ポートの空き状況を先に確認すべきだった。",[202,203,208],"pre",{"className":204,"code":205,"language":206,"meta":207,"style":207},"language-bash shiki shiki-themes vitesse-light vitesse-light","# 次回からはこれを先に叩く\npowershell \"Get-NetTCPConnection -State Listen | Where-Object { $_.LocalPort -lt 10000 }\"\n","bash","",[30,209,210,219],{"__ignoreMap":207},[211,212,215],"span",{"class":213,"line":214},"line",1,[211,216,218],{"class":217},"sxvE3","# 次回からはこれを先に叩く\n",[211,220,222,226,230,234,238,241],{"class":213,"line":221},2,[211,223,225],{"class":224},"senZ8","powershell",[211,227,229],{"class":228},"sMJiu"," \"",[211,231,233],{"class":232},"sdGka","Get-NetTCPConnection -State Listen | Where-Object { ",[211,235,237],{"class":236},"snbK4","$_",[211,239,240],{"class":232},".LocalPort -lt 10000 }",[211,242,243],{"class":228},"\"\n",[73,245,246],{"id":246},"表示確認の結果",[15,248,249],{},"Chrome DevToolsで以下を確認した:",[91,251,252,258,264],{},[59,253,254,257],{},[62,255,256],{},"書籍一覧ページ",": 登録済みの書籍がカード形式で並ぶ。税法入門が追加されている",[59,259,260,263],{},[62,261,262],{},"ページナビゲーション",": 前後ページへの移動が動作する。107ページの最終ページまで辿れる",[59,265,266,269],{},[62,267,268],{},"コンテンツ表示",": OCRテキストがページ単位で表示される。図の参照箇所も画像として埋め込まれている",[15,271,272],{},"全て正常動作を確認した。",[19,274],{},[22,276,277],{"id":277},"学びメモ",[91,279,280,286,296],{},[59,281,282,285],{},[62,283,284],{},"レプリカ配置はプロジェクト群の近くに",": ホームディレクトリのドットフォルダに隠すと、存在を忘れる。目に入る場所に置いた方が管理が続く",[59,287,288,291,292,295],{},[62,289,290],{},"ポートの空き確認は起動前に",": 「3000が空いてるだろう」という思い込みで3回サーバーを再起動した。",[30,293,294],{},"Get-NetTCPConnection"," を先に叩くだけで数分節約できた",[59,297,298,301],{},[62,299,300],{},"FTS5の互換性は実際にクエリを投げて確かめる",": ドキュメントに「対応」と書いてあっても、実環境で検索結果が返ってくるまでは安心しなかった。前日にCodexから指摘を受けていなければ、ここまで丁寧に検証しなかったと思う",[19,303],{},[22,305,306],{"id":306},"今日の作業まとめ",[308,309,310,323],"table",{},[311,312,313],"thead",{},[314,315,316,320],"tr",{},[317,318,319],"th",{},"作業",[317,321,322],{},"状態",[324,325,326,335,342,349,356,363,370],"tbody",{},[314,327,328,332],{},[329,330,331],"td",{},"Embedded Replicaドキュメント整理",[329,333,334],{},"完了",[314,336,337,340],{},[329,338,339],{},"レプリカディレクトリ配置変更",[329,341,334],{},[314,343,344,347],{},[329,345,346],{},"turso-replicasリポジトリ初期化",[329,348,334],{},[314,350,351,354],{},[329,352,353],{},"FTS5互換性検証",[329,355,334],{},[314,357,358,361],{},[329,359,360],{},"税法入門OCR（107ページ・14図）",[329,362,334],{},[314,364,365,368],{},[329,366,367],{},"Turso DB格納",[329,369,334],{},[314,371,372,375],{},[329,373,374],{},"devサーバー表示確認",[329,376,334],{},[378,379,380],"style",{},"html pre.shiki code .sxvE3, html code.shiki .sxvE3{--shiki-default:#A0ADA0;--shiki-dark:#A0ADA0}html pre.shiki code .senZ8, html code.shiki .senZ8{--shiki-default:#59873A;--shiki-dark:#59873A}html pre.shiki code .sMJiu, html code.shiki .sMJiu{--shiki-default:#B5695977;--shiki-dark:#B5695977}html pre.shiki code .sdGka, html code.shiki .sdGka{--shiki-default:#B56959;--shiki-dark:#B56959}html pre.shiki code .snbK4, html code.shiki .snbK4{--shiki-default:#A65E2B;--shiki-dark:#A65E2B}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":207,"searchDepth":221,"depth":221,"links":382},[383,384,388,389,393,399,400],{"id":24,"depth":221,"text":25},{"id":41,"depth":221,"text":41,"children":385},[386],{"id":75,"depth":387,"text":75},3,{"id":83,"depth":221,"text":84},{"id":135,"depth":221,"text":136,"children":390},[391,392],{"id":139,"depth":387,"text":140},{"id":163,"depth":387,"text":164},{"id":175,"depth":221,"text":176,"children":394},[395,396,397,398],{"id":182,"depth":387,"text":183},{"id":189,"depth":387,"text":190},{"id":196,"depth":387,"text":197},{"id":246,"depth":387,"text":246},{"id":277,"depth":221,"text":277},{"id":306,"depth":221,"text":306},"dev","book-knowledge-baseのSQLite書籍DBをTurso Embedded Replicaに移行した作業ログ。レプリカ配置の見直し、税法入門107ページのOCR→DB格納、Chrome DevToolsでのポート試行錯誤を経て表示確認まで完了","md",{},true,null,"/turso-book-db-migration","book-knowledge-base",false,"2026-04-11T00:00:00.000Z",{"title":5,"description":402},"2026-04/2026-04-11/turso-book-db-migration",[414,415,416,417,418,419,408],"Turso","Embedded Replica","SQLite","yomitoku","OCR","Chrome DevTools","memo","Pl8H4aLCUTiGf8c7e10Sursy4Qdk1I0xryjgKoL2r4c",[],"https://log.eurekapu.com/og/blog/turso-book-db-migration.png?v=2026-04-11T00%3A00%3A00.000Z&title=Turso%20Embedded%20Replica%E3%81%A7%E6%9B%B8%E7%B1%8DDB%E3%82%92%E7%A7%BB%E8%A1%8C%20-%20OCR%E3%83%87%E3%83%BC%E3%82%BF%E6%A0%BC%E7%B4%8D%E3%81%8B%E3%82%89dev%E7%A2%BA%E8%AA%8D%E3%81%BE%E3%81%A7&author=Kei%20Komatsu&sig=55589f998122ecd4",1782528826427]