欄位型別:資料的心智模型
欄位型別同時決定三件事:前端要呈現哪一種輸入控制項、API 接受哪一種 JSON 值,以及資料是直接儲存還是在讀取時推導。先選對型別,之後的驗證、查詢與顯示才不會互相矛盾。
欄位型別地圖
編號序列 是 string 的伺服器指派選項,不是另一種 enum 值。設定最外層的 sequence 後,用戶端讀取格式化字串,但不能提供或替換編號;一般 string 欄位仍可寫入。
下表涵蓋已記錄的後端型別,包括已合併的 principal_list,以及已合併的座標型別。decimal 以字串保存精確定點數,scale 決定小數位數;interval 以 {start, end} 保存半開日期時間範圍;json 直接存任意 JSON 文件。三個單一 principal 型別各存一個本租戶身分:principal 是帶 user:<id>、smc:<id> 或 room:<id> 標籤的字串,較舊的 user 與 social_client 則存裸 id。principal_list 改存帶標籤身分的陣列。需要自己的人員 metadata 時,人員表加 link 仍是正確模型。
| 群組 | 型別 | Cell 形狀 | 儲存與寫入 | 詳細說明 |
|---|---|---|---|---|
| 文字 | string | 字串 | 存在 record.data,一般可寫;sequence 則由伺服器指派 | 字串與長文 |
| 文字 | text | 字串 | 存在 record.data,可寫 | 字串與長文 |
| 數值 | integer | 整數 | 存在 record.data,可寫 | 整數與浮點數 |
| 數值 | float | 數字 | 存在 record.data,可寫 | 整數與浮點數 |
| 數值 | decimal | 小數位數固定為欄位 scale 的小數字串,例如 "1290.50" | 存在 record.data,可寫 | 定點小數 |
| 位置 | coordinate | 完整的軸鍵物件,各值都是小數字串 | 存在 record.data;已合併 PR1。距離篩選與排序:座標查詢 | 座標 |
| 邏輯 | boolean | true / false | 存在 record.data,可寫 | 布林值 |
| 時間 | date | YYYY-MM-DD 字串 | 存在 record.data,可寫 | 日期與日期時間 |
| 時間 | datetime | YYYY-MM-DD HH:mm 字串 | 存在 record.data,可寫 | 日期與日期時間 |
| 時間 | interval | { "start": "YYYY-MM-DD HH:mm", "end": "YYYY-MM-DD HH:mm" } | 存在 record.data,可寫 | 區間 |
| 選項 | select | 一個選項字串 | 存在 record.data,可寫 | 單選與多選 |
| 選項 | multi_select | 選項字串陣列 | 存在 record.data,可寫 | 單選與多選 |
| 檔案 | attachment | 附件陣列 | blob ID 存在 record.data,可寫 | 附件 |
| 文件 | json | 任意 JSON 值:物件、陣列或純量 | 存在 record.data,可寫 | JSON |
| Principal | principal | 寫入是帶標籤的 user:<id>/smc:<id>/room:<id> 字串;讀取是 {ref, kind, id, name, …} | 存在 record.data,可寫 | Principal 欄位 |
| Principal | principal_list | 最多 100 個不重複的帶標籤身分陣列 | 存在 record.data,可寫 | Principal 清單 |
| Principal | user | 寫入是 User.id 原始字串;讀取是 {id, name, username, is_deleted} | 存在 record.data,可寫 | Principal 欄位 |
| Principal | social_client | 寫入是 SocialMediaClient.id 原始字串;讀取是 {id, platform, name} | 存在 record.data,可寫 | Principal 欄位 |
| 關聯 | link | 目標紀錄 ID 陣列 | 存在獨立連結表,可寫 | 連結 |
| 推導 | rollup | 數字、小數字串、日期或 null | 讀取時計算,唯讀 | 彙總 |
| 推導 | lookup | 純量、陣列或 null | 讀取時計算,唯讀 | 查找 |
| 推導 | formula | 數字、小數字串、布林、字串或 null | 預設 live;v2 可儲存受保護結果,唯讀 | 公式、v2/stored |
注意 Link 值在關聯表;
rollup、lookup與 liveformula在讀取時計算,不儲存在record.data。Formula 預設為formula_version: 1與computation_mode: "live";v2 stored formula 必須同時設定formula_version: 2與computation_mode: "stored",才會在交易內於record.data維護受保護、唯讀的結果。attachment不屬於計算欄;它會把 blob ID 存在record.data,讀取時再展開成已遮蔽 URL 的附件資料。interval、json與 principal 型別都是直接內嵌儲存且可寫,但 principal cell 在讀取時會被轉換:單一身分成為顯示物件,principal_list則包含多個身分,而在本租戶已無法解析的值會維持原始字串。只有principalcell 讀取時會帶ref與kind——user與social_client逐位元維持原本的 dict 形狀,前端就是靠這點分辨兩者。
user指三件不同的事user是 ACL 與 IaC 的授權對象種類(grant principal kind)——權限授予給誰。user同時也是一種欄位型別——紀錄裡的一格。而user:還是principal欄位裡的一種 cell 標籤。三者只是共用同一個字。
用戶端能力矩陣
這是 schema editor 可直接採用的精簡跨介面模型。「Unique / IaC key」先表示能否成為 unique 規則成分,再表示是否適合當 IaC record natural key。
| 型別 | 值模式 | REST 查詢篩選 | REST 排序 | CSV/XLSX 匯入 | Unique / 安全 IaC key |
|---|---|---|---|---|---|
string | inline;sequence 值由伺服器指派 | stored_filters | 可以 | 字串 | 可以 / 可以 |
text | inline,可寫 | stored_filters | 可以 | 字串 | 可以 / 可以 |
integer | inline,可寫 | stored_filters | 可以 | 數字字串 | 可以 / 可以 |
float | inline,可寫 | stored_filters | 可以 | 數字字串 | 可以 / 可以 |
decimal | inline 小數字串,可寫 | stored_filters:以小數字串運算元做數值比較,不支援 contains | 可以,依數值 | 純小數字串;XLSX 需 preserve_text_cells=true 且來源為文字格式 cell | 可以 / 可以 |
boolean | inline,可寫 | stored_filters | 可以 | 只在明確指定 boolean 目標時:true/false 文字(不分大小寫) | 可以 / 不行 |
date | inline,可寫 | stored_filters,含相對日期 | 可以 | 標準日期字串 | 可以 / 可以 |
datetime | inline,可寫 | stored_filters,含相對日期 | 可以 | YYYY-MM-DD HH:MM;接受 T 分隔與秒數並截斷,offset 會被拒絕 | 可以 / 可以 |
interval | inline {start, end} 物件,可寫 | stored_filters:overlaps、contains_point、presence | 可以,依 start | 拒絕;檔案 cell 無法組成物件 | 不行 / 不行 |
select | inline,可寫 | stored_filters | 可以 | 完全相符的 option 字串 | 可以 / 可以 |
multi_select | inline 陣列,可寫 | 舊版 filters membership;stored_filters encoded-array oddity* | 目前是 encoded-array oddity* | 不行;importer 提供字串 | 不行 / 不行 |
attachment | inline blob-ID 陣列,可寫;讀取時加工 | 只有 presence | 不行 | 每個 cell 一個屬於本租戶的 blob ID,或 blob ID 的 JSON 陣列 | 不行 / 不行 |
json | inline JSON,可寫 | 只有 whole-cell 純量等值 | 不行 | 拒絕 | 不行 / 不行 |
principal | inline 帶標籤字串,可寫;讀取時加工 | 只有帶標籤 cell 等值 | 不行 | 只接受本租戶帶標籤 cell | 可以 / 可以 |
user | inline 原始 ID,可寫;讀取時加工 | 只有原始 ID 等值 | 不行 | 只接受本租戶原始 ID | 可以 / 可以 |
social_client | inline 原始 ID,可寫;讀取時加工 | 只有原始 ID 等值 | 不行 | 只接受本租戶原始 ID | 可以 / 可以 |
link | 可寫的 relation-ID 陣列,不在 inline data | membership 與 presence | 不行 | 拒絕 | 只限 cardinality-one / 不行 |
rollup | 讀取時計算,唯讀 | computed_filters | 有條件的單欄排序† | 拒絕 | 不行 / 不行 |
lookup | 讀取時計算,唯讀 | 只限純量 one/picked lookup† | 只限純量 one/picked lookup† | 拒絕 | 不行 / 不行 |
formula | 預設 live;v2 支援受保護 stored 結果,唯讀 | computed_filters | 有條件的單欄排序† | 拒絕 | 不行 / 不行 |
* 「包含某個 option」請使用舊版 filters map。後端也接受 multi_select 進入 stored_filters 或當 sort key,但兩條路都比較整個已儲存陣列的 JSON_UNQUOTE 字串形式,不理解個別元素,也不是穩定的產品篩選/排序合約。用戶端不應依賴這兩種 encoded-array 行為。
† 計算欄篩選/排序使用 computed_filters 與單欄 sort_by,不屬於 stored filter 或多欄排序。Lookup 必須呈現單一純量(cardinality-one 或帶 pick 的 many lookup),而且不能帶 eval-only 的 fallback;computed-sort guard 也會拒絕 live rows 超過 50,000 的表。
最後一欄談的是 key,不代表所有規則家族。其他規則各自有 operator 與型別 gates。IaC 請使用具有穩定等值表示的 inline scalar:string/text、integer/float/decimal、date/datetime、select 或 principal(decimal 鍵會先正規化到欄位的 scale 再比對)。Boolean、JSON 與複合 interval 物件會被明確拒絕;list-valued、relation、attachment 與 derived cell 都不是安全的 record-matching key。各介面的 wire rule 差異見檔案匯入、查詢與遷移。
JSON 與單一 principal 的特殊能力限制
json 刻意不算已儲存純量,而三種單一 principal 型別都算。principal_list 是陣列,不在這個純量比較表內。這個差異決定了下表大部分內容:
| 能力 | json | principal | user / social_client |
|---|---|---|---|
| REST 過濾 | 只能等值、運算元須為純量:eq、neq、in、is_null、is_not_null | 只能等值,且運算元必須是帶標籤的 cell | 只能等值、運算元須為原始 id |
| 可排序 | 否 | 否 | 否 |
REST group_by / metric | 否 | group_by 可以(標籤是鍵的一部分);count/count_distinct 可以 | group_by 可以;count 與 count_distinct 可以,sum/avg/min/max 不行 |
name_eq / name_contains | 否 | 不行——先解析,再用 ref 過濾 | 可以 |
| Formula 引用 | 否 | 否 | 否 |
| Rollup / lookup 目標 | 否 | 可以(lookup 帶出的是原始帶標籤字串) | 可以(lookup 帶出的是原始 id,不是顯示物件) |
unique 規則成分 | 否 | 可以 | 可以 |
require 規則 | 可以——但 {} 與 [] 算「有填」 | 可以 | 可以 |
Upsert 的 match_column | 否 | 可以 | 可以 |
| ACL row policy / SCP 葉節點 | 否 | 可以,只能等值——ACL row policy 裡的 $me 解析成一個集合;SCP 葉節點只收 literal | 可以,只能等值——ACL row policy 裡的 $me 解析成單一 id;SCP 葉節點只收 literal |
| IaC 自然鍵 | 否 | 可以 | 可以 |
| cell 內的 IaC 身分 token | 否 | $user: / $smc: / $room:——存成帶標籤 cell | $user: / $smc: |
send_channel_message 收件人 | 否 | 否 | social_client 可以,user 不行 |
invoke_command 的 $row 輸入 | 否 | 只能餵 string 參數 | identity: 參數或 string |
| CSV/XLSX 匯入目標 | 否 | 可以,但來源 cell 必須是屬於本租戶的帶標籤 cell | 可以,但來源 cell 必須是屬於本租戶的原始身分 ID 字串 |
這四種型別都一律拒絕 default_value、max_length、options,也都不接受任何附件、decimal 或計算欄設定欄位。
建立欄位的共同形狀
對既有表新增欄位,使用 columns.create。每個型別頁的「建立 schema」都只顯示該端點的 JSON body;範圍與 table_id 由路徑提供。
{
"name": "訂單編號",
"type": "string",
"required": true,
"default_value": "待編號",
"description": "外部 ERP 的訂單識別碼",
"max_length": 32
}純量欄可以使用 required 與型別相符的 default_value,但 multi_select 與 attachment 不接受預設值。只有 string 與 text 會強制執行 max_length;integer、float、boolean、date 與 datetime 接受它但會忽略。select 與 multi_select 必須提供 options,而 select 的 default_value 必須是其中一個選項。decimal 欄位另外必須提供 precision、scale 與 allow_negative,其 default_value 要用小數字串,並拒絕 max_length 與 options。link 與推導欄不可設 required、default_value 或 max_length:columns.create、columns.preview 與 tables.create(針對 schema_definition 中的欄位)會以 422 驗證錯誤拒絕。對 rollup、lookup 或 formula 欄位送出非 null 值的紀錄 payload,會以 400 拒絕(<Type> column '<col_key>' is computed and read-only)。interval、json、principal、user、social_client 只接受 required 與 description。在 columns.create、columns.preview 與 tables.create 上,於這五種型別或 attachment 宣告 default_value、max_length 或 options,以及在 decimal 上宣告 max_length 或 options,都會在建立任何東西之前以 422 失敗,detail 會列出驗證錯誤。之後執行的檢查在 columns.create 上回 400:options 清單缺少、為空、超過 50 項,或含有空字串、超過 64 字或重複的選項(不是字串清單的 options 值會更早以 422 失敗)、select 或 multi_select 帶 max_length、string、text、integer、float、boolean、date、datetime、link 或推導欄帶 options、任何 multi_select 預設值、不在 options 內的 select 預設值,以及與 string、integer、float、boolean、date 或 datetime 欄位不相符的 default_value。columns.preview 只重跑其中與預設值型別相關的檢查:multi_select 預設值、非字串的 select 預設值,以及與 string、integer、float、boolean、date 或 datetime 欄位不相符的預設值會得到 valid: false;但缺少 options 清單或清單違反上述限制、select 或 multi_select 帶 max_length、上面列出的其他型別帶 options,以及不在 options 內的 select 預設字串,預覽結果都是 valid: true。在 columns.update 上,對不接受預設值的欄位型別送出非 null 的 default_value 是 400。對已有 live 紀錄的表新增 required 欄位時必須提供 default_value,因此必填的 multi_select、attachment、interval、json 或 principal 欄位只能加到沒有 live 紀錄的表。
欄位身分:顯示名稱與內部鍵
建立時送出的 name 是給人看的顯示名稱,例如「訂單編號」。伺服器同時產生穩定的內部鍵,例如 col_c3333333_3333_4333_8333_333333333333,並放進 settings.column_mapping。顯示名稱可以改,內部鍵不變;查詢、更新紀錄與推導欄的持久化引用因此不會因改名失效。完整規則請見欄位身分。
選型原則
- 要讓使用者自由輸入:選
string、text、數值、布林或日期型別。 - 金額等必須精確到固定小數位數的數值:選
decimal,並以小數字串交換其值;只有在二進位捨入誤差可以接受時才用float。 - 要把一組開始/結束日期時間當成單一值移動與驗證:選
interval。 - 要限制在受控字典:選
select或multi_select。 - 要附加檔案:選
attachment,先上傳 blob,再把 blob ID 寫入 cell。 - 要原樣保留一份半結構化資料——webhook body、ERP 封包、每列各自的設定——選
json。但要接受它不能排序、不能當鍵值,也不能餵給 formula。 - 要指向負責人:選
principal。一格可以放user:<id>、smc:<id>或room:<id>,所以同一欄能指向同事、客戶的聊天身分,或整個聊天室(成員繼承該指派)。user與social_client留給既有的單一種類欄位。三者都是$merow policy 比對的對象。若你需要的是屬於自己 schema 的人員 metadata,改用人員表加link。 - 要建立表間關係:先建
link;要顯示目標欄用lookup,要彙總目標列用rollup。 - 要用欄位組合出新值:選
formula;它與 lookup 一樣唯讀,但公式是運算,不是單純帶出目標值。
試試看
到 API Playground 選擇 columns.create,或用連結與彙總流程精靈實際建立跨表欄位。