JSON 文件
使用點記法讀寫巢狀 JSON object 與 array,同時由 ToriiDB 維持 parsed cache 一致性。
儲存表示
只有當值為有效 JSON,且外層是 object 或 array 時,才會分類為 json。每個 Entry 會把 serialized string 放在未匯出的 value field,並可在 parsed 中保留解析後 object。
| 方法 | 角色 |
|---|---|
Value() |
回傳原始 serialized value |
JSON() |
序列化所有持久化 entry field,包含未匯出的 value |
parseAndCache() |
Cache miss 時解析;呼叫端必須持有寫鎖或處於單執行緒流程 |
cached() |
持有讀鎖時讀取已預熱的 cache |
setParsed(obj) |
同步序列化並快取修改後 object |
此設計可避免 raw value 與 parsed representation 分離。
點記法路徑
Exec 會把第一個點拆成頂層 key 與 subkey list:
user.profile.level
└── key: user
└── path: profile, level
Object path 使用 field name;array path 使用十進位 index:
SET user {"name":"Torii","tags":["go","database"],"profile":{"level":1}}
GET user.name
GET user.tags.0
GET user.profile.level
空白 path component 會被忽略。Field operation 要求頂層 key 儲存 JSON value。
欄位寫入
欄位層級 SET 會呼叫 SetField:
SET user.profile.level 2
SET user.profile.active true
缺少的 object map 會自動建立。既有 array 可以被走訪,但 array index 必須能解析為 integer 且在範圍內。若最終 path component 前遇到 scalar,操作會失敗。
NX 與 XX 針對頂層 key 判斷,不是個別 field。欄位層級 SET 不支援 VECTOR。
欄位讀取與型別
GET user.profile.level
EXIST user.profile.level
TYPE user.profile.level
GetField 會從 entry lookup、cache access 到 WalkKeys 全程持有資料庫讀鎖。Value 透過 utils.Vtoa 呈現;TypeField 再對呈現結果套用一般型別偵測。
數值欄位
IncrField 要求目標是數值:
INCR user.profile.level
INCR user.profile.level 0.5
它透過 WalkKeys 讀值、以 Vtof 轉換、用 setParsed 寫回結果、更新 entry timestamp,再持久化完整文件。
欄位刪除
將單一 dotted key 傳給 DEL 可刪除該 field:
DEL user.profile.active
Object property 會被移除。若路徑指向 array,刪除會把該 element 設為 JSON null,而不是縮短 array。
若 DEL 同時傳入多個 key,則執行頂層 key 刪除,不會進行 field deletion。
並行規則
SetField、IncrField與DelField持有資料庫寫鎖。GetField與Query存取 parsed object 時持有讀鎖。- 每個 JSON write path 都會在釋放寫鎖前呼叫
setParsed。 - Replay 會在並行讀取開始前為 JSON entry 預熱 parsed cache。