データ取り込み・正規化・名寄せの設計
法令データの自前資産化可否は e-Gov 法令API の「別表構造化・施行日別リビジョン・収録範囲」の3点で実測判定する
1日前
法令・規制の判定支援や改正追従を商品にするプロダクトでは、条文・別表のマスタと改正差分を自前データ化できるかが事業可否のゲートになる。日本の法令はこの可否を e-Gov 法令API(v2、認証・利用申込み不要)への実測3点で着手前に判定できる(2026-08 に実レスポンスで確認)。
判定の3点
- 別表・表構造が構造化ノードで返るか — 法令全文は JSON/XML(法令標準XMLスキーマ)で取得でき、別表は TableRow/TableColumn の構造化テーブル、条文は項・号・イロハの階層ノードで表現される。テキストの塊や画像参照ではないことを対象法令ごとに確認する(画像添付の有無はレスポンスの添付ファイル情報で分かる)
- 施行日別リビジョンが取れるか — 法令ごとにリビジョン一覧 API があり、任意の施行日時点の全文を取得できる。新旧2時点を突合すれば細目(号・イロハ)粒度の改正差分が機械計算できる
- そもそも収録対象か — 法律・政令・省令は収録されるが、告示・通達は基本的に未収録(法令名検索のヒット0件で判別できる)。告示ベースのデータ(統計品目表・料率表など)は所管官庁サイトの PDF 告示が原資になり、構造化抽出の工数がそのまま参入障壁=製品価値側に回る
検証手順
法令名で検索して法令IDを特定 → 全文取得 → 別表ノードの構造確認 → リビジョン一覧取得 → 2時点の全文を突合して差分計算、の順に小さく実測する。ここまで通れば「改正追従を売るデータ層」が技術的に成立する。
権利面の落とし穴
法令・告示の本文は著作権法13条で権利の対象外、e-Gov・政府サイトは政府標準利用規約系(出典明記で商用可)が基本。ただし政府サイトに転載された国際機関等の第三者著作物は適用除外なので、サイト規約と配布ファイル本文の権利表記を必ず二層で確認する。
非可逆な正規化(slugify等)をキーにした保存は、キー一致で同一性を判定しない — 本文に原文を保存し読み出し時に完全一致照合する
1日前
キャッシュ・成果物ファイル・レポートなどを「正規化したキー(slugify、空白→ハイフン、記号除去、長さ切り詰め等)」で保存するとき、その正規化が非可逆なら別の入力が同じキーに潰れる(例: 「ai agent」と「ai-agent」、記号を含む語と含まない語、先頭 N 文字が同じ長い語)。キーの一致だけで「同じ対象のデータ」と判定すると、別対象の結果を黙って返す取り違えが起きる。下流が追記専用の台帳や課金処理なら、汚染は静かに永続化する。
実装規則
- 保存時: 本文(ペイロード)に正規化前の原文キー(と同一性に関与する全次元。例: 検索語と市場・ロケール)をそのまま保存する
- 読み出し時: ファイル名一致は「候補の発見」にのみ使い、本文の原文キーが要求値と完全一致するかを照合してから使う。不一致は「キャッシュ不在」と同じ扱い(fail-soft なら再取得へフォールバック)
- テスト: 正規化で同一キーに潰れるペア(空白/ハイフン差・記号有無)を意図的に作り、互いにヒットしないことを固定する。次元の片方だけ変えたケース(同じ語・別ロケール)も別ケースで固定する
なぜキー側の工夫では解決しないか
- エスケープを可逆にする選択肢もあるが、ファイル名には長さ上限・使用不可文字があり、完全に可逆なキーは可読性と衝突する。「見やすいキー+本文照合」の二段構えが実用上の落としどころ
- 関連原則: 別コンポーネントが後で照合する ID は照合側の正準形に合わせる(書き込み時正規化)。本件はその逆方向の補題 — 正規化が情報を捨てる場合は、正規化形を同一性の根拠に格上げしない
正規化するパイプラインでは、原本(一次情報)の観測とシステムが保持する事実は食い違う
3日前
取り込んだデータについて「実データはこうなっている」と主張するとき、どの観測点で見たかで結論が変わる。取得した原本を直読みするスクリプトと、本番と同じパーサ・正規化を通して保存された値では、見える事実が違う。
実例の型: 公表資料の台帳に全角数字が1件混在する。これを原本直読みで見つけて「実データに全角が実在するので検査を緩める必要がある」と判断したが、取り込みパーサは以前から該当列を正規化してから格納しており、保存後のデータに全角は1件も無かった。緌めた検査は、本来 fail-closed にしたいガードを fail-open へ反転させていた。
判断基準
- 「一次情報を見る」は外部仕様の確認には正しいが、自システムが保持する事実の確認には正しくない。変換を伴う取り込みでは、確かめるべき観測点は入力側ではなく本番と同じ経路を通った出力側
- データの事実を根拠に実装を変えるときは、その観測がどの経路を通ったかを先に宣言する。書き捨ての確認スクリプトは本番経路をバイパスしやすい
- この取り違えは実装を緩める方向へ傾く。「汚い入力が実在する」と信じると、本来厳密にできる検査に正規化や例外を添えてしまう
委譲しているときに効く
実装を他者(人でも AI でも)へ委ねていると、この種の誤認は完了報告の中に「実データで確認済み」として現れるため見抜きにくい。さらにその報告をレビュー側へ渡すと、レビュアーも同じ前提の上で指摘を組み立てるので、誤った前提が複数の工程を通って増幅される。
- データの事実を主張する報告は、主張だけでなく観測経路(どこをどう見たか)を完了報告の契約に含める
- 検証の安い順番は、報告を読む側がすでに動いている本番・実環境へ直接問い合わせること。代替実装を書いて確かめるより速く、しかも経路の取り違えが起きない
- 誤認が判明したら、それを前提に出された指摘・実装をまとめて見直す(一部だけ直すと、緩められた検査が残る)
外部が件数を公表しないデータ取り込みでは、内部の連番完全性と前回比で自前のチェックサムを作る
3日前
外部の公表資料を定期取り込みするパイプラインでは、掲載ページに書かれた件数とパース結果の件数を照合する fail-closed ゲートが最も効く。取得と解析が独立に壊れても、外部が宣言した値と食い違えば止まるためだ。問題は、同種の資料でも件数を公表していないソースがあること。パース結果の件数を自分で数えて記録するだけでは自己参照で、何も検証していない。
代替ゲートの作り方
資料の内部に、行の欠落や重複を外から検算できる構造が残っていることが多い。表形式の一覧なら通し番号の列がその代表。
- 連番の完全性を fail-closed 条件にする。最小値から最大値まで欠番がなく、重複もないことを検証する。行の取りこぼしと重複読みはここで止まる。
- ただし連番検証は末尾切れを検知できない(1からNまで揃っているが、本来N+M件あった)。この穴は前回反映済みの件数との比較で塞ぐ。減少が一定割合を超えたら止める。増加側は正常な成長と区別できないので止めない。初回取り込みには適用しない。
- 資料内の記載日付が複数ファイルに分かれている場合、日付が揃っていることも検証条件に入れる。版の食い違う資料を黙って混ぜない。
検知器として検証する
この種のゲートは実装した時点では動作が確認されていない。故意に壊した検体を通して、期待どおり非ゼロ終了するかを確かめて初めてゲートになる。壊し方は1種類で済ませず、ゲートが担保する制約ごとに別の壊し方を用意する。
- 通し番号を1つ抜いた入力 → 連番検証で停止
- 同じ番号を2行持つ入力 → 重複検出で停止
- 前回の反映件数に対して大幅に少ない入力 → 前回比ガードで停止
- 記載日付が食い違う複数ファイル → 版不一致で停止
検体は実ファイルから採取して加工したものを使う。手組みのみだと、実データの表記ゆれ(全角半角の混在、和暦、囲み文字など)を通る保証がない。
適用条件
外部の宣言値が取れるなら、そちらを優先する。自前のゲートは代替であって上位互換ではない(資料の生成側が壊れていて連番ごとおかしいケースは検知できない)。宣言値が無いソースに限って使い、無いことをドキュメントに理由として残す。
名寄せキーの粒度は、正規化を強くする前に実データの衝突を実測して決める
3日前
組織名や人名を突合するとき、表記ゆれを吸収するために正規化(全角半角の統一、空白除去、法人格や敬称の除去)をかける。この正規化は強くするほど表記ゆれに強くなる一方で、実在する別実体を同一のキーへ潰す方向にも効く。名称の一部が接頭・接尾の除去対象と重なっていると、正式名称が異なる別法人が同じキーになる。
判断基準
- 正規化の強度を落として解決しようとしない。除去をやめれば別実体の同一化は解けるが、表記ゆれ吸収という本来の目的を失い、突合対象すべての名寄せが崩れる。爆発半径が桁違いに大きい。
- 代わりにキーの次元を足す。名称に地理的な絞り(都道府県相当 → 市区町村相当)を重ねる方向は、既存キーを壊さず衝突だけを解く。政令市のように市の下にさらに区がある体系では、区まで含めないと解けない衝突が実在する。
- 一意制約を「名称+広い地域」から「名称+広い地域+狭い地域」へ移すのは制約を緩める方向なので、既存データは必ず通る。移行時に既存行が制約違反で落ちる心配が要らないのは、この向きだけ。
実測してから決める
キーの候補ごとに、取り込む全データ(新規ソースだけでなく既存データとの突合も)でキーを計算し、衝突キー数と潰れる件数を数える。設計時のコメントに「衝突したら手動レビュー」と書いてあっても、実データに既に衝突があれば初回取り込みが必ず落ちるので運用が成立しない。
同時に測っておくべきもの:
- 抽出できない入力の件数。住所からの地域抽出は、国外住所・記載欠落・別言語表記で失敗する。追加するキー列は NULL 相当(空文字)を許す設計にする。
- 新旧ソースの重なり。既存データと新ソースが同一実体としてどれだけ名寄せされるかは、後段の属性更新規則の設計を左右する(重なりが多数派なら、属性の上書き規則は例外処理ではなく主要な設計事項になる)。
落とし穴
- キーの次元を足すと、既に1行へ潰れていた実体は自動では分かれない。次回の取り込みで新しいキーとして新規作成され、旧行は更新されない孤児として残る。孤児の掃除は別作業として見積もる。
- 一意制約に NULL 可の列が含まれると、多くの RDB は NULL 同士を重複扱いしないため、その組み合わせには制約が効かない。追加する列を NOT NULL(既定は空文字)にしておくと、少なくとも新しく増える穴は作らない。
「正準値→検索候補」の逆引きは正引きから導出する — 保存が原文のままなら片側手書きが検索漏れを生む
6日前
保存側が入力の原文(表記ゆれを含む)をそのまま持ち、検索は正準値から候補集合を作って完全一致で照合する構成での判断。
問題の型
表示は「原文 → 正準値」の正引きだけで足りるが、検索には「正準値 → 原文候補」の逆引きが要る。この逆引きを辞書として手で持つと、正引きと非対称になる。特に落ちやすいのは次の2種類。
- 正規化で形が変わる表記(ダッシュ・括弧・空白の全角半角など)。逆引きが正規化後の形を返すと、原文のまま保存された行と完全一致せず 0 件になる
- 正引きが動的に分解する複合値(1セルに複数の値が区切りなしで連結しているようなもの)。分解結果は正準値になるが、連結された原文自体はどの逆引きにも載らない
症状は「詳細画面には正しく表示されるのに、検索とファセット件数からは消えている」という非対称で、表示側だけ見ていると気付けない。
判断
逆引きを手で持たず、既知の原文集合を正引きに通して機械的に導出する。こうすると「正引き(x) がキー K を返すならば x は必ず 逆引き(K) に含まれる」が構造的に成立し、辞書を編集するたびに両方向を手で同期する必要がなくなる。
検証方法
実データから採取した原文集合の全件について、上記の対称性を表明するテストを置く。逆引きが返す値を正引きできることだけを確認するテストは、逆引きに載っていない原文を入力に取らないため反証にならない(構造上ほぼ恒真になる)。反証力があるのは「実データの原文を入力にする」方向のテストだけ。
適用条件と例外
検索基盤側にクエリ時正規化の仕組み(アナライザ相当)があるなら、そちらで吸収する方が素直で、逆引き辞書は不要になる。逆引き方式は「保存を原文のままにしたい」「正規化を後から変更できるようにしたい」という要求があるときの選択で、その対価としてこの対称性の担保が要る。
外部公開データの厳格フォーマット検証はNFKC正規化してから行い、件数チェックサムで実データとの整合を確認する
6日前
官公庁・団体等が公開する台帳データ(Excel/CSV等)を、正規表現などの厳格なフォーマット検証(ID・番号・コード列の型チェック)にかけつつ、別途「公開ページ記載の件数」のような一次情報の件数と突き合わせるチェックサム検証を組み合わせるパイプラインでは、検証を素の文字列に対して厳格に適用すると、データ入力側の表記ゆれ(全角/半角数字・カナの混在、全角記号の混入など)で本来正当なレコードが弾かれ、チェックサムが恒常的に不一致になることがある。
判断基準: 外部データソースのID/番号列を正規表現等で厳格検証する際は、検証・格納の直前に Unicode NFKC 正規化を通してから照合する。これにより全角/半角混在という表記ゆれ由来の誤検出を吸収しつつ、構造的に異なる(列がずれている、フォーマットが根本的に違う等)壊れたデータは正規化後も依然としてマッチしないため、検証としての意味は失わない。
適用条件: (1) 検証対象が「意味は同じだが文字コードが揺れている」ことが起こりうる自由入力由来の列であること(人手入力の官公庁台帳、CSV輸出など)、(2) 別途、件数や合計のような独立した一次情報でチェックサム照合を行っており、正規化なしだと数件〜数十件規模の正当なレコードが恒常的に弾かれてチェックサムを満たせない、という2条件がある場合に適用する。
落とし穴: 正規化の適用範囲を検証対象列だけに限定すること。数値専用列(郵便番号等、全桁が意味のある数字で構成される列)に対して「先頭の数字らしき文字を除去する」ような周辺の防御的処理を安易に流用すると、正規化ではなくデータ破壊になる。列ごとに正規化してよい理由(表記ゆれの許容範囲)を明確にしてから適用する。
検証方法: 実データ全件に対して「チェックサム件数と実際にマッチした件数が一致するか」を実行して確認する。1件でも構造的に不一致な場合は、正規化で吸収すべき表記ゆれなのか、本当にデータ破損・パースロジックの誤りなのかを、不一致の具体的な行を人手で確認してから切り分ける(正規化を先に適用してから原因調査を省略しない)。