使用 FluentSQLite 连接表时列名不明确

Ambiguous column name when joining tables with FluentSQLite

我正在尝试编写一条路线,returns 特定用户关注的用户所写的所有帖子。这是我正在使用的数据模型:

struct Follow: Content, SQLiteModel, Migration {
    var id: Int?
    var follower: String
    var following: String
}

struct Post: Content, SQLiteModel, Migration {
    var id: Int?
    var username: String
    var message: String
}

struct User: Content, SQLiteStringModel, Migration {
    var id: String?
    var password: String
}

这是路线:

router.get(String.parameter, "timeline") { req -> Future<[Post]> in
    let username = try req.parameters.next(String.self)

    return Follow.query(on: req).filter(\Follow.follower == username).join(\Follow.following, to: \Post.username).alsoDecode(Post.self).all().map { tuples in
        return tuples.map { tuple in
            return tuple.1
        }
    }
}

代码编译,但在运行时我得到这个 JSON 错误字典:

{"error":true,"reason":"ambiguous column name: main.Follow.id"}

而且我也有一个想法,问题是因为我在做一个join,然后有一个重复的id字段(Follow.id,Post.id),但是如何解决这个问题?在 sql 中,我只想指定类似 'as followId' 的内容来重命名该字段,但是如何在 FluentSQLite 中执行此操作?

更新

最后我是这样修改"timeline"路由的:

return User.find(username, on: req).flatMap { user in
    guard let user = user else {
        throw Abort(.notFound)
    }

    return try user.followers.query(on: req)
        .join(\Post.username, to:\FollowUp.following)
        .alsoDecode(Post.self).all()
        .flatMap { tuples in
        return tuples.map { tuple in
            return tuple.1
        }
    }
}

我收到此错误:"Cannot convert value of type '[Post]' to closure result type 'EventLoopFuture<[Post]>'"

Follow 本质上是 Pivot table 并正式实施它应该可以解决您的问题。但是,你可以运行陷入困境,参见:

因此,在您的情况下,将您的 followerfollowing 字段设为 User.ID 类型并将以下内容添加到您的 Follow 模型中:

struct Follow: Content, Pivot, Migration
{
    static var idKey: WritableKeyPath<FollowUp, Int?> = .id
    typealias Database = SQLiteDatabase
    typealias ID = Int
    var id:Int?
    var follower:User.ID
    var following:User.ID

    typealias Left = User
    typealias Right = User

    static var leftIDKey: WritableKeyPath<Follow, Int> {
        return \.follower
    }

    static var rightIDKey: WritableKeyPath<Follow, Int> {
        return \.following
    }
}

然后创建这个扩展:

extension User:
{
    var followers: Siblings<User, User, Follow> {
    return siblings(Follow.leftIDKey, Follow.rightIDKey)
    }
}

所以,最后,您的查询变为:

return User.find(username, on: req).flatMap { user in
    guard let user = user else {
        throw Abort(.notFound)
    }

    return try user.followers.query(on: req)
        .join(\Post.username, to:\FollowUp.following)
        .alsoDecode(Post.self).all()
        .map { tuples in
        return tuples.map { tuple in
            return tuple.1
        }
    }
}

您需要调整 Post 以保持 User.ID 而不是 username 才能使连接生效。