欄位型別:19 種資料的心智模型
欄位型別同時決定三件事:前端要呈現哪一種輸入控制項、API 接受哪一種 JSON 值,以及資料是直接儲存還是在讀取時推導。先選對型別,之後的驗證、查詢與顯示才不會互相矛盾。
19 種型別地圖
下表是目前後端 ColumnType 的完整集合:19 個值全部列出,沒有省略其他 enum 值。interval 以 {start, end} 物件保存一個半開日期時間範圍,json 直接存一份任意 JSON 文件,而三個 principal 型別各內嵌存一個本租戶的身分。現在該用的是 principal:它的 cell 是單一帶標籤的字串——user:<id>、smc:<id> 或 room:<id>——所以同一欄可以指向內部使用者、社群客戶,或整個聊天室(成員繼承該指派)。user 與 social_client 是較舊的單一種類型別,存的是裸 id。當你需要自己的人員 metadata 時,人員表加 link 仍然是正確模型,但它已經不是表示負責人的唯一方式。
| 群組 | 型別 | Cell 形狀 | 儲存與寫入 | 詳細說明 |
|---|---|---|---|---|
| 文字 | string | 字串 | 存在 record.data,可寫 | 字串與長文 |
| 文字 | text | 字串 | 存在 record.data,可寫 | 字串與長文 |
| 數值 | integer | 整數 | 存在 record.data,可寫 | 整數與浮點數 |
| 數值 | float | 數字 | 存在 record.data,可寫 | 整數與浮點數 |
| 邏輯 | 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 | 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 | 讀取時計算,唯讀 | 公式 |
注意
link、rollup、lookup、formula都不把 cell 值寫進record.data:link 值在關聯表,另外三種在讀取時計算。attachment不屬於計算欄;它會把 blob ID 存在record.data,讀取時再展開成已遮蔽 URL 的附件資料。interval、json與三個 principal 型別都是直接內嵌儲存且可寫,但 principal cell 在讀取時會被轉換:寫進去是身分字串、讀回來是顯示物件,而在本租戶已無法解析的值會維持原始字串。只有principalcell 讀取時會帶ref與kind——user與social_client逐位元維持原本的 dict 形狀,前端就是靠這點分辨兩者。
user指三件不同的事user是 ACL 與 IaC 的授權對象種類(grant principal kind)——權限授予給誰。user同時也是一種欄位型別——紀錄裡的一格。而user:還是principal欄位裡的一種 cell 標籤。三者只是共用同一個字。
19 種型別的用戶端能力矩陣
這是 schema editor 可直接採用的精簡跨介面模型。「Unique / IaC key」先表示能否成為 unique 規則成分,再表示是否適合當 IaC record natural key。
| 型別 | 值模式 | REST 查詢篩選 | REST 排序 | CSV/XLSX 匯入 | Unique / 安全 IaC key |
|---|---|---|---|---|---|
string | inline,可寫 | stored_filters | 可以 | 字串 | 可以 / 可以 |
text | inline,可寫 | stored_filters | 可以 | 字串 | 可以 / 可以 |
integer | inline,可寫 | stored_filters | 可以 | 數字字串 | 可以 / 可以 |
float | inline,可寫 | stored_filters | 可以 | 數字字串 | 可以 / 可以 |
boolean | inline,可寫 | stored_filters | 可以 | 不行;檔案 cell 仍是字串 | 可以 / 不行 |
date | inline,可寫 | stored_filters,含相對日期 | 可以 | 標準日期字串 | 可以 / 可以 |
datetime | inline,可寫 | stored_filters,含相對日期 | 可以 | 只接受標準分鐘字串 | 可以 / 可以 |
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 | 不行 | 不行;需要 ID 陣列 | 不行 / 不行 |
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 | 讀取時計算,唯讀 | 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、數值、date/datetime、select 或 principal。Boolean、JSON 與複合 interval 物件會被明確拒絕;list-valued、relation、attachment 與 derived cell 都不是安全的 record-matching key。各介面的 wire rule 差異見檔案匯入、查詢與遷移。
JSON 與 principal 的特殊能力限制
json 刻意不算已儲存純量,而三種 principal 型別都算。這一個差異就決定了下表大部分內容:
| 能力 | 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,也都不接受任何附件或計算欄設定欄位。
建立欄位的共同形狀
對既有表新增欄位,使用 columns.create。每個型別頁的「建立 schema」都只顯示該端點的 JSON body;範圍與 table_id 由路徑提供。
{
"name": "訂單編號",
"type": "string",
"required": true,
"default_value": "待編號",
"description": "外部 ERP 的訂單識別碼",
"max_length": 32
}純量欄可以使用 required、型別相符的 default_value,而 max_length 只適用於 string / text。推導欄是唯讀資料,因此不可設 required、default_value 或 max_length。interval、json、principal、user、social_client 只接受 required 與 description——在這五種型別上宣告 default_value、max_length 或 options,欄位在建立前就會被拒絕。
欄位身分:顯示名稱與內部鍵
建立時送出的 name 是給人看的顯示名稱,例如「訂單編號」。伺服器同時產生穩定的內部鍵,例如 col_c3333333_3333_4333_8333_333333333333,並放進 settings.column_mapping。顯示名稱可以改,內部鍵不變;查詢、更新紀錄與推導欄的持久化引用因此不會因改名失效。完整規則請見欄位身分。
選型原則
- 要讓使用者自由輸入:選
string、text、數值、布林或日期型別。 - 要把一組開始/結束日期時間當成單一值移動與驗證:選
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,或用連結與彙總流程精靈實際建立跨表欄位。