简体   繁体   中英

Vapor 4, How to filter by Foreign Key?

I have two models (UserModel and UserTokenModel)

UserTokenModel has a ForeignKey that indicates UserModel.

Here is my code. I tried to filter by userModel's Id on UserTokenModel but I got an error.

Operator function '==' requires that 'UUID' conform to 'QueryableProperty'

if let user = try await UserModel.query(on: req.db).filter(\.$email == request.email).first() {
    //Compile Error: Operator function '==' requires that 'UUID' conform to 'QueryableProperty'
    let userToken = try await UserTokenModel.query(on: req.db)
    .filter(\.$user.id == user.$id).first()
}

Here is definition of Models

final class UserModel: Model {
    static let schema = "user_users"
    
    struct FieldKeys {
        static var email: FieldKey { "email" }
        static var password: FieldKey { "password" }
        static var appleId: FieldKey { "appleId" }
        static var givenName: FieldKey { "givenName" }
        static var familyName: FieldKey { "familyName" }
        static var userName: FieldKey { "userName" }
    }
    
    //MARK:- fields
    @ID() var id: UUID?
    @Field(key: FieldKeys.email) var email: String
    @Field(key: FieldKeys.password) var password: String
    @Field(key: FieldKeys.appleId) var appleId: String?
    @Field(key: FieldKeys.givenName) var givenName: String?
    @Field(key: FieldKeys.familyName) var familyName: String?
    @Field(key: FieldKeys.userName) var userName: String?
    
    init() {}
    
    init(id: UserModel.IDValue? = nil,
         email: String,
         password: String,
         appleId: String? = nil,
         givenName: String? = nil,
         familyName: String? = nil,
         userName: String? = nil
    ) {
        self.id = id
        self.email = email
        self.password = password
        self.appleId = appleId
        self.givenName = givenName
        self.familyName = familyName
        self.userName = userName
    }
}

UserTokenModel

final class UserTokenModel: Model {
    static let schema = "user_tokens"
    
    struct FieldKeys {
        static var value: FieldKey { "value" }
        static var userId: FieldKey { "user_id" }
    }
    
    //MARK:- fields
    
    @ID() var id: UUID?
    @Field(key: FieldKeys.value) var value: String
    @Parent(key: FieldKeys.userId) var user: UserModel
    
    init() {}
    init(
        id: UserTokenModel.IDValue? = nil,
        value: String,
        userId: UserModel.IDValue
    ) {
        self.id = id
        self.value = value
        $user.id = userId
    }
}

You need to change your code to:

if let user = try await UserModel.query(on: req.db).filter(\.$email == request.email).first() {
    guard let userId = user.id
    else { throw SomeError() }
    //Compile Error: Operator function '==' requires that 'UUID' conform to 'QueryableProperty'
    let userToken = try await UserTokenModel.query(on: req.db)
    .filter(\.$user.$id == userId).first()
}

The QueryableProperty error is due to you not putting in the $ in front of the id in the LHS of the filter. If you fixed this, you would then have got an error about the user.id property being Optional . Introducing the guard fixes this and allows you to handle the error if the user doesn't exist.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM