Search code examples
vaporvapor-fluentserver-side-swift

how do vapor fluent do a upsert?


I have a table named profile, and my model here:

final class Profile: Model, Content {
    struct Keys {
        static let userId: FieldKey = "user_id"
        static let nickname: FieldKey = "nickname"
        static let bio: FieldKey = "bio"
    }
    
    static let schema = "profile"
    
    @ID(key: .id) var id: UUID?
    
    @Field(key: Keys.nickname) var nickname: String?
            
    @Field(key: Keys.bio) var bio: String?
    
    @Parent(key: Keys.userId) var user: User
    
    init() {}
    
    init(id: UUID? = nil, nickname: String?, bio: String?, userId: User.IDValue) {
        self.id = id
        self.nickname = nickname
        self.bio = bio
        self.$user.id = userId
    }
}

And I got request body content from client like this:

{
  "bio": "my new bio"
}

What I want is for the client to update whichever property it passes, there is my code to do this:

let userId = try req.auth.require(User.self).requireID()
guard let oldProfile = try await Profile.query(on: req.db).filter(\.$user.$id == userId).first() else {
    let newProfile = Profile(nickname: edit.nickname, bio: edit.bio, userId: userId)
    try await newProfile.save(on: req.db)
    return GlobalResponse(code: .ok, msg: .custom("save success"))
}

if let b = edit.bio {
    oldProfile.bio = b
}

if let n = edit.nickname {
    oldProfile.nickname = n
}

try await oldProfile.update(on: req.db)
return GlobalResponse(code: .ok, msg: .custom("save success"))

Those code works fine, but is there a better or easier way to do this? I did not find a easy way to do upsert work.

I just started learning vapor.

I try to find some upsert code in vapor fluent, did comes nothing.


Solution

  • Fluent does not currently support upserts, primarily because of the complexities of supporting it in all supported databases in a generic way.

    You can drop down to SQLKit to perform the upserts however, that will work fine.