使用 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 上工作的详细信息,请参阅此页面,它实际上是作为单个事务进行的。