使用 PostgreSQL 的 Vapor、fluent save/create 复杂模型
Vapor, fluent save/create complex model with PostgreSQL
我正在尝试将模型保存到 PostgreSQL 数据库。问题是,我无法正确保存子模型。
当我保存模型时,它只保存没有任何关系的 ID。我做错了什么?
请求正文已正确设置为 POST 请求。我不知道如何将模型字段与另一个 model/array 模型连接。
创建方法:
func create(req: Request) async throws -> CollectionResponse {
let todo = try req.content.decode(CollectionResponse.self)
try await todo.save(on: req.db)
return todo
}
迁移
struct CreateCollection: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema("collection")
.id()
.field("childrenArray", .custom([Object()]))
.create()
}
func revert(on database: Database) async throws {
try await database.schema("collection").delete()
}
}
struct CreateCollectionObject: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema("collectionObject")
.id()
.field("personalID", .string, .required)
.field("title", .string)
.field("thumbnail", .string)
.field("model_a_id", .uuid, .required, .references(CollectionResponse.schema, .id))
.create()
}
func revert(on database: Database) async throws {
try await database.schema("collectionObject").delete()
}
}
型号:
final class CollectionResponse: Model, Content, Codable{
static var schema: String = "collection"
@ID(key: .id)
var id: UUID?
@Children(for: \.$modelA)
var childrenArray: [Object]
init() { }
init(id: UUID? = UUID(), childrenArray: [Object] = []) {
self.id = id
self.childrenArray = childrenArray
}
}
final class Object: Model, Content, Codable{
static var schema: String = "collectionObject"
@ID(key: .id)
var id: UUID?
@Field(key: "perosnalID")
var personalID: String?
@Field(key: "title")
var title: String?
@Field(key: "thumbnail")
var thumbnail: String?
@Parent(key: "model_a_id")
var modelA: CollectionResponse
init() { }
init(id: UUID? = UUID(), perosnalID: String?, title: String?, thumbnail: String?, modelA: UUID = UUID()) {
self.id = id
self.personalID = personalID
self.title = title
self.thumbnail = thumbnail
self.$modelA.id = modelA
}
}
您的 create
路线中的 save
不会保存 todo
中的任何子对象。这是你的责任。我还没有更改为 async
方法,但最初在 vapor 4 中执行此操作的方法是先保存父对象,然后捕获 id
并更新子对象,以便它们具有正确的外键值。类似于:
func create(req: Request) async throws -> CollectionResponse {
let todo = try req.content.decode(CollectionResponse.self)
return todo.save(on: req.db).flatMap { _ in
// todo has been updated with the primary key field value
todo.childrenArray.map{ [=10=].$modelA.$id = todo.$id }
todo.childrenArray.save(on: req.db).flatMap { _ in
return todo
}
}
}
按照 https://docs.vapor.codes/4.0/fluent/model/ 中的指南一致地命名字段和属性是个好主意。有关数组保存如何在 childrenArray
上工作的详细信息,请参阅此页面,它实际上是作为单个事务进行的。
我正在尝试将模型保存到 PostgreSQL 数据库。问题是,我无法正确保存子模型。 当我保存模型时,它只保存没有任何关系的 ID。我做错了什么? 请求正文已正确设置为 POST 请求。我不知道如何将模型字段与另一个 model/array 模型连接。
创建方法:
func create(req: Request) async throws -> CollectionResponse {
let todo = try req.content.decode(CollectionResponse.self)
try await todo.save(on: req.db)
return todo
}
迁移
struct CreateCollection: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema("collection")
.id()
.field("childrenArray", .custom([Object()]))
.create()
}
func revert(on database: Database) async throws {
try await database.schema("collection").delete()
}
}
struct CreateCollectionObject: AsyncMigration {
func prepare(on database: Database) async throws {
try await database.schema("collectionObject")
.id()
.field("personalID", .string, .required)
.field("title", .string)
.field("thumbnail", .string)
.field("model_a_id", .uuid, .required, .references(CollectionResponse.schema, .id))
.create()
}
func revert(on database: Database) async throws {
try await database.schema("collectionObject").delete()
}
}
型号:
final class CollectionResponse: Model, Content, Codable{
static var schema: String = "collection"
@ID(key: .id)
var id: UUID?
@Children(for: \.$modelA)
var childrenArray: [Object]
init() { }
init(id: UUID? = UUID(), childrenArray: [Object] = []) {
self.id = id
self.childrenArray = childrenArray
}
}
final class Object: Model, Content, Codable{
static var schema: String = "collectionObject"
@ID(key: .id)
var id: UUID?
@Field(key: "perosnalID")
var personalID: String?
@Field(key: "title")
var title: String?
@Field(key: "thumbnail")
var thumbnail: String?
@Parent(key: "model_a_id")
var modelA: CollectionResponse
init() { }
init(id: UUID? = UUID(), perosnalID: String?, title: String?, thumbnail: String?, modelA: UUID = UUID()) {
self.id = id
self.personalID = personalID
self.title = title
self.thumbnail = thumbnail
self.$modelA.id = modelA
}
}
您的 create
路线中的 save
不会保存 todo
中的任何子对象。这是你的责任。我还没有更改为 async
方法,但最初在 vapor 4 中执行此操作的方法是先保存父对象,然后捕获 id
并更新子对象,以便它们具有正确的外键值。类似于:
func create(req: Request) async throws -> CollectionResponse {
let todo = try req.content.decode(CollectionResponse.self)
return todo.save(on: req.db).flatMap { _ in
// todo has been updated with the primary key field value
todo.childrenArray.map{ [=10=].$modelA.$id = todo.$id }
todo.childrenArray.save(on: req.db).flatMap { _ in
return todo
}
}
}
按照 https://docs.vapor.codes/4.0/fluent/model/ 中的指南一致地命名字段和属性是个好主意。有关数组保存如何在 childrenArray
上工作的详细信息,请参阅此页面,它实际上是作为单个事务进行的。