尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

PostgREST 如何用 domain 与 CAST 自定义字段的展示格式并支持按短格式过滤

PostgREST 如何用 domain 与 CAST 自定义字段的展示格式并支持按短格式过滤 PostgREST 如何用 domain 与 CAST 自定义字段的展示格式并支持按短格式过滤【免费下载链接】postgrestREST API for any Postgres database项目地址: https://gitcode.com/GitHub_Trending/po/postgrestPostgREST 的 Domain Representations 机制把数据如何展示与数据如何存储分开在数据库中用domain定义类型再用castCAST告诉 PostgREST 在展示和接收数据时使用另一种格式。本文以uuid主键为例完成一条完整路径让profiles表的id列以 base64 短格式出现在 JSON 响应里并支持直接用短格式值做水平过滤horizontal filtering。示例中 PostgREST 服务运行在http://localhost:3000响应格式选用 JSON。1. 创建 domain 并用作表的主键类型基于uuid创建 domain并用它作为表的主键列类型插入一条示例数据create domain app_uuid as uuid; -- and use it as our table PK. create table profiles( id app_uuid , name text ); -- some data for the example insert into profiles values (846c4ffd-92ce-4de7-8d11-8e29929f4ec4, John Doe);注意如果表已经存在且列类型是原生uuid需要先把列改成app_uuid。文档说明 domain 与其底层类型是 binary coercible 的关系这种列类型变更不需要重写表是一个快速操作。2. 配置 JSON 响应使用短格式创建一个把app_uuid转成json的函数函数名可以任意取用base64编码缩短uuid-- the name of the function is arbitrary CREATE OR REPLACE FUNCTION json(app_uuid) RETURNS json AS $$ select to_json(encode(uuid_send($1),base64)); $$ LANGUAGE SQL IMMUTABLE; -- check it works select json(846c4ffd-92ce-4de7-8d11-8e29929f4ec4::app_uuid);文档示例输出json ---------------------------- hGxP/ZLOTeeNEY4pkp9OxA然后创建 CAST让 PostgREST 在请求 JSON 响应时自动调用这个函数做转换CREATE CAST (app_uuid AS json) WITH FUNCTION json(app_uuid) AS IMPLICIT;文档特意说明从展示角度base58编码更 URL-friendly但这里为了简单使用base64因为 PostgreSQL 原生支持。创建 domain 上的 CAST 之后必须刷新 PostgREST 的 schema cache否则新格式不会生效。刷新方式见 Schema Cache Reloading向进程发SIGUSR1信号或从数据库内发送NOTIFY pgrst, reload schema;。验证按 Response Format 用Accept头指定 JSON 请求该表curl http://localhost:3000/profiles \ -H Accept: application/json文档示例返回短格式出现在响应中[{id:hGxP/ZLOTeeNEY4pkp9OxA,name:John Doe}]3. 支持用短格式值做水平过滤PostgREST 把 URL 查询串在通用意义上视为text所以要让ideq.短格式这类过滤条件生效需要一个text到app_uuid的转换函数和 CAST-- the name of the function is arbitrary CREATE OR REPLACE FUNCTION app_uuid(text) RETURNS app_uuid AS $$ select substring(decode($1,base64)::text from 3)::uuid; $$ LANGUAGE SQL IMMUTABLE; -- plus a CAST to tell PostgREST to use this function CREATE CAST (text AS app_uuid) WITH FUNCTION app_uuid(text) AS IMPLICIT;之后按 Horizontal Filtering 的常规语法过滤直接用短格式值注意文档示例中该值在 URL 里从hGxP/ZLOTeeNEY4pkp9OxA取ZLOTeeNEY4pkp9OxA部分curl http://localhost:3000/profiles?ideq.ZLOTeeNEY4pkp9OxA \ -H Accept: application/json文档示例返回[{id:hGxP/ZLOTeeNEY4pkp9OxA,name:John Doe}]边界说明如果没有定义text到app_uuid的 CAST过滤仍可用但必须写原生uuid格式846c4ffd-92ce-4de7-8d11-8e29929f4ec4。同理若不定义json到app_uuid的 CAST请求体也仍按原生uuid格式工作。4. 可选在请求体中接收短格式如果需要插入或更新时也能提交短格式例如创建新记录再定义json到app_uuid的转换复用前面的app_uuid(text)函数-- the name of the function is arbitrary CREATE OR REPLACE FUNCTION app_uuid(json) RETURNS public.app_uuid AS $$ -- here we reuse the previous app_uuid(text) function select app_uuid($1 # {}); $$ LANGUAGE SQL IMMUTABLE; CREATE CAST (json AS public.app_uuid) WITH FUNCTION app_uuid(json) AS IMPLICIT;按 Insert 的方式 POST用Prefer: returnrepresentation让响应带回写入的资源curl http://localhost:3000/profiles \ -H Prefer: returnrepresentation \ -H Content-Type: application/json \ -d - JSON {id:zH7HbFJUTfy/GZpwuirpuQ,name:Jane Doe} JSON文档示例响应[{id:zH7HbFJUTfy/GZpwuirpuQ,name:Jane Doe}]在数据库侧查询可以看到存储的仍是常规uuid格式select * from profiles;id | name -------------------------------------------------- 846c4ffd-92ce-4de7-8d11-8e29929f4ec4 | John Doe cc7ec76c-5254-4dfc-bf19-9a70ba2ae9b9 | Jane Doe (2 rows)5. 为什么不用视图以及已知限制Domain Representations 文档对比了视图VIEW方案视图格式化列有三个代价domain CAST 方案都没有这些问题列在视图中被格式化后变成不可更新non-updatable因为 Postgres 不知道怎么反转转换需要 INSTEAD OF trigger 绕开按格式化列过滤会全表扫描需要计算索引或物化生成列来补救若格式化列作为外键PostgREST 检测不到该关系resource embedding 会失效需要 computed relationship 绕开。domain 方案的唯一代价是对已有表要变更列类型且如前所述不需要重写表。另外文档明确提示domain 上的 CAST 会被 PostgreSQL 本身忽略其解释权交给应用程序PostgREST相关行为还在 pgsql-hackers 讨论中——所以这套机制依赖 PostgREST 消费这些 CAST。6. 后续维护schema cache 刷新每次创建或修改 domain 上的 CAST、转换函数后都要刷新 schema cachekillall -SIGUSR1 postgrestDocker 下docker kill -s SIGUSR1 container或NOTIFY pgrst, reload schema;。如果数据库 DDL 频繁变化可以按 Automatic Schema Cache Reloading 建 event trigger在ddl_command_end时自动发NOTIFY pgrst, reload schema;之后无需手动刷新。最后核对一次完成状态GET 请求返回短格式id?ideq.短格式过滤能命中对应行而select * from profiles;里存的仍是原生uuid——三者同时成立说明展示格式与过滤格式都已按 domain CAST 配置生效。【免费下载链接】postgrestREST API for any Postgres database项目地址: https://gitcode.com/GitHub_Trending/po/postgrest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表