Kent Shen
← 所有文章

做公司關係圖譜時學到的事:登記資料是「事件」,不是「現況」

  • Undercurrent
  • 資料工程
  • D1

Undercurrent 是我做的公司與法人關係圖譜工具:輸入姓名、公司名或統一編號,就能看到對應的董監事、經理人,以及一個人跨公司任職的關聯。它背後的資料全部來自政府公開資料,而處理這些資料的過程,比做畫面更花時間。

資料是「事件記錄」

我後來匯入司法院開放資料平台的「法人登記公告資料集」(財團法人與社團法人),一共 115 個年度的 JSON 檔,大小約 322MB。拿到之後我才發現一件事:這份資料不是「現況清單」,而是「異動事件記錄」。

同一個法人每次設立、變更、屆期改選,都會新增一筆資料,不會覆蓋舊的。而且它沒有類似統一編號那種穩定的識別碼,只能靠法人名稱跨年份比對。要查某個法人的「現況」,邏輯是:撈出這個名稱底下所有的記錄,取登記日期最新的一筆。

這個差異很重要。如果當成現況清單直接使用,你會同時看到一個基金會的三任董事長,卻不知道誰才是現任。處理這類資料的第一步,永遠是先搞清楚每一列代表的是「一個東西」還是「一次變化」。

為什麼把官方資料搬進自己的資料庫

Undercurrent 早期查詢是即時呼叫外部 API。這有兩個問題:速度取決於對方,而且一次搜尋一個人,可能得連續打好幾次外部請求。

後來我把經濟部 GCIS 的董監事與經理人資料整批匯入自己的 D1 資料庫,排程設成每月一次,跟官方的資料更新頻率對齊。現在的查詢順序是:先查自己的資料庫,查不到才退回官方 API 當備援。之前還有一個社群維護的第三方備援來源,穩定之後完全用不到,我就把相關程式碼整個拿掉了。備援層數越少,出問題時要排查的地方就越少。

還沒搬進來的是公司的資本額、地址、設立日期這類欄位,那是另一個資料集。所以使用者點開某間公司的側欄時,這些欄位仍會即時查官方 API,但範圍已經縮小成「使用者主動點開才觸發一次」。

一個典型的 N+1 問題

上線後我發現,查一個在很多間公司任職的人,前端會對每間公司各發一次請求。這就是 N+1 查詢:一次查人,再加上 N 次查公司。

解法是新增一支合併端點,由伺服器一次完成「用姓名找公司」以及「用 WHERE ubn IN (...) 一次撈出這些公司的完整名單」。前端現在不管這個人身兼幾間公司的董監事,都只發一個請求。

另外還有一個有趣的反轉:批次匯入階段,我為了節省寫入額度拿掉了統編的索引,因為當時的查詢是 LIKE '%關鍵字%',索引幫不上忙。等查詢方式改成精確比對之後,我又把索引加回來。索引不是越多越好,也不是越少越好,要看查詢實際長什麼樣子。

使用上的提醒

關係圖譜呈現的是公開登記的資料,同名同姓的人很常見。我加了右鍵隱藏節點的功能,讓使用者把混進來的無關公司直接點掉,這只影響顯示,不會動到資料庫。圖譜只是線索,不是結論。

你可以到 Undercurrent 試用。