Vapor/Fluent中schema定义uuid数组字段时子对象无法保存问题
问题产生原因
你遇到的报错已经明确指出了类型不匹配的核心问题:
{"error":true,"reason":"server: column "sources" is of type uuid[] but expression is of type jsonb[] (transformAssignedExpr)"}
具体是两层定义不一致导致的:
- 数据库迁移中你将
sources字段定义为.array(of: .uuid),对应Postgres侧的uuid[]类型,仅支持存储UUID格式的数组 - 模型层你将
sources字段声明为[Coin]类型,Fluent会默认将所有遵循Codable协议的自定义类型序列化为JSONB格式存储,哪怕传入空数组,也会生成JSONB数组类型的写入请求,和数据库要求的UUID数组类型冲突。
正确实现方案
方案1:存储来源Coin的UUID数组(推荐,符合回溯链路的设计初衷)
这种方案仅存储来源Coin的ID,无冗余数据,是最常用的实现方式:
- 修改模型层的
sources字段定义:
// 原定义 @Field(key: "sources") var sources: [Coin] 替换为 @Field(key: "sources") var sources: [UUID]
- 调整初始化方法的赋值逻辑,提取传入Coin实例的ID存入数组:
init(player: User, quantity: Int, type: CreatedFor, sources : [Coin] = []) { self.id = id self.$player.id = player.id! self.quantity = quantity self.type = type self.sources = sources.compactMap(\.id) }
- 恢复迁移代码中
sources字段的注释即可,不需要修改数据库侧的类型定义。
方案2:存储完整的Coin实体信息
如果业务场景需要将来源Coin的全量信息直接存在字段中,不需要关联查询,仅需要修改迁移中的字段类型:
// 原定义 .field("sources", .array(of: .uuid)) 替换为 .field("sources", .array(of: .jsonb))
模型层的sources: [Coin]定义不需要调整,Fluent会自动完成序列化存储。
可选方案:用多对多关联管理来源关系
如果后续需要基于来源Coin做反向查询、统计等操作,更推荐使用Fluent的多对多关联实现:
- 新建中间表
CoinSources,存储当前CoinID、来源CoinID两个关联字段 - 给Coin模型添加
@Siblings修饰符管理来源关联关系,无数据冗余,查询更灵活
内容的提问来源于stack exchange,提问作者Dan Donaldson
相关产品推荐
相关产品推荐

