使用 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 并正式实施它应该可以解决您的问题。但是,你可以运行陷入困境,参见:
因此,在您的情况下,将您的 follower
和 following
字段设为 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
才能使连接生效。
我正在尝试编写一条路线,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 并正式实施它应该可以解决您的问题。但是,你可以运行陷入困境,参见:
因此,在您的情况下,将您的 follower
和 following
字段设为 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
才能使连接生效。