Vapor 中相同模型之间的兄弟姐妹关系
Siblings relationship between same models in Vapor
我有一个 User
模型,我想在其中添加一个 friends
属性。朋友,应该是其他User
s.
我创建了 UserFriendsPivot
:
final class UserFriendsPivot: MySQLPivot, ModifiablePivot {
var id: Int?
var userID: User.ID
var friendID: User.ID
typealias Left = User
typealias Right = User
static var leftIDKey: WritableKeyPath<UserFriendsPivot, Int> {
return \.userID
}
static var rightIDKey: WritableKeyPath<UserFriendsPivot, Int> {
return \.friendID
}
init(_ user: User, _ friend: User) throws {
self.userID = try user .requireID()
self.friendID = try friend.requireID()
}
}
extension UserFriendsPivot: Migration {
public static var entity: String {
return "user_friends"
}
}
我将 friends
属性 添加到 User
:
var friends: Siblings<User, User, UserFriendsPivot> {
return siblings()
}
现在,我在 return siblings()
行中看到以下错误:
Ambiguous use of 'siblings(related:through:)'
我尝试将其替换为:
return siblings(related: User.self, through: UserFriendsPivot.self)
...运气不好。
我知道这两个代码片段 应该 有效,因为我直接从我在 Event
和 User
之间建立的另一个兄弟姐妹关系中复制了它们那工作得很好。
我看到的唯一区别是我正在尝试在相同模型之间建立关系。
我能做什么?
尝试用类似以下内容替换您的 friends
定义:
var friends: Siblings<User,UserFriendsPivot.Right, UserFriendsPivot> {
return User.siblings()
}
编辑:
它应该像 table 一样与 Left
和 Right
一起工作,但似乎失败了,因为别名解析为基值。 IE。 Xcode 中的自动完成显示 siblings
的所有候选者最终都属于以下类型:
Siblings<User, User, UserFriendsPivot> siblings(...)
而不是:
Siblings<User, UserFriendsPivot.Right, UserFriendsPivot> siblings(...)
和类似的。
我建议在 GitHub 上提出错误。同时,如何使用不同的名称和设置创建 User
的副本:
static let entity = "User"
使用相同的物理 table。不漂亮,但它可能会让你工作。
这里的问题是,在同一个 Model
(User-User
) 兄弟姐妹关系中,Fluent 无法推断你指的是哪个兄弟姐妹——需要指定双方。
extension User {
// friends of this user
var friends: Siblings<User, User, UserFriendsPivot> {
siblings(UserFriendsPivot.leftIDKey, UserFriendsPivot.rightIDKey)
}
// users who are friends with this user
var friendOf: Siblings<User, User, UserFriendsPivot> {
siblings(UserFriendsPivot.rightIDKey, UserFriendsPivot.leftIDKey)
}
}
另一个相同的-Model
后果是您将无法使用附加便捷方法添加到数据透视表table,而需要手动创建:
let pivot = try UserFriendsPivot(user, friend)
pivot.save(on: req)
(还有其他方法可以解决这个问题,我只是发现上面这些简单的方法最容易使用。指定边和反转关键位置以获得反比关系是重要的概念。)
回答
我有一个 User
模型,我想在其中添加一个 friends
属性。朋友,应该是其他User
s.
我创建了 UserFriendsPivot
:
final class UserFriendsPivot: MySQLPivot, ModifiablePivot {
var id: Int?
var userID: User.ID
var friendID: User.ID
typealias Left = User
typealias Right = User
static var leftIDKey: WritableKeyPath<UserFriendsPivot, Int> {
return \.userID
}
static var rightIDKey: WritableKeyPath<UserFriendsPivot, Int> {
return \.friendID
}
init(_ user: User, _ friend: User) throws {
self.userID = try user .requireID()
self.friendID = try friend.requireID()
}
}
extension UserFriendsPivot: Migration {
public static var entity: String {
return "user_friends"
}
}
我将 friends
属性 添加到 User
:
var friends: Siblings<User, User, UserFriendsPivot> {
return siblings()
}
现在,我在 return siblings()
行中看到以下错误:
Ambiguous use of 'siblings(related:through:)'
我尝试将其替换为:
return siblings(related: User.self, through: UserFriendsPivot.self)
...运气不好。
我知道这两个代码片段 应该 有效,因为我直接从我在 Event
和 User
之间建立的另一个兄弟姐妹关系中复制了它们那工作得很好。
我看到的唯一区别是我正在尝试在相同模型之间建立关系。
我能做什么?
尝试用类似以下内容替换您的 friends
定义:
var friends: Siblings<User,UserFriendsPivot.Right, UserFriendsPivot> {
return User.siblings()
}
编辑:
它应该像 table 一样与 Left
和 Right
一起工作,但似乎失败了,因为别名解析为基值。 IE。 Xcode 中的自动完成显示 siblings
的所有候选者最终都属于以下类型:
Siblings<User, User, UserFriendsPivot> siblings(...)
而不是:
Siblings<User, UserFriendsPivot.Right, UserFriendsPivot> siblings(...)
和类似的。
我建议在 GitHub 上提出错误。同时,如何使用不同的名称和设置创建 User
的副本:
static let entity = "User"
使用相同的物理 table。不漂亮,但它可能会让你工作。
这里的问题是,在同一个 Model
(User-User
) 兄弟姐妹关系中,Fluent 无法推断你指的是哪个兄弟姐妹——需要指定双方。
extension User {
// friends of this user
var friends: Siblings<User, User, UserFriendsPivot> {
siblings(UserFriendsPivot.leftIDKey, UserFriendsPivot.rightIDKey)
}
// users who are friends with this user
var friendOf: Siblings<User, User, UserFriendsPivot> {
siblings(UserFriendsPivot.rightIDKey, UserFriendsPivot.leftIDKey)
}
}
另一个相同的-Model
后果是您将无法使用附加便捷方法添加到数据透视表table,而需要手动创建:
let pivot = try UserFriendsPivot(user, friend)
pivot.save(on: req)
(还有其他方法可以解决这个问题,我只是发现上面这些简单的方法最容易使用。指定边和反转关键位置以获得反比关系是重要的概念。)
回答