在Vapor中,我们可以通过创建一个Pivot<U, T>
对象来创建多到多的关系,其中U
和T
是我们希望链接在一起的模型。因此,如果我想创建一个系统,其中User
s可以有很多File
,很多File
可以属于许多User
,那么我将它们联系在一起如下:
var alice = User(name: "Alice")
try! alice.save()
var sales = File(name: "sales.xclx")
try! sales.save()
var pivot = Pivot<User, File>(alice, sales)
try! pivot.save()
我不知道我的一生是如何使Pivot<User, File>
包含更多信息的?例如,我想知道这个文件是何时与Alice相关联的,或者她对它有什么权限。
在关系数据库上,Fluent为Pivot<User, File>
类型创建此表。
+---------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| file_id | int(11) | NO | | NULL | |
| user_id | int(11) | NO | | NULL | |
+---------+---------+------+-----+---------+----------------+
但我希望能代表这样的东西:
+---------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| file_id | int(11) | NO | | NULL | |
| user_id | int(11) | NO | | NULL | |
| date | date | NO | | NULL | |
| perms | varchar | NO | | READ | |
+---------+---------+------+-----+---------+----------------+
发布于 2016-11-14 08:21:44
Pivot<U, T>
对象可以被认为是像siblings
这样的枢轴关系所需的“最低限度”字段。
如果要向此表添加自定义字段,则可以创建自己的类作为支点,只要它具有所需的元素:
Foo
和Bar
的表名是bar_foo
(小写,按字母顺序排列)id
、bar_id
、foo_id
换句话说,由pivot类创建的表必须至少具有Pivot<Foo, Bar>
准备所创建的元素。
这样,您就可以通过创建和保存pivot类的实例来创建新的枢轴关系。
当在使用此透视表的模型上调用.siblings()
关系时,仍然会创建默认的Pivot<U, T>
来执行提取。但是,这不会产生任何问题,因为所需的字段存在于pivot表中。
发布于 2017-01-17 02:49:05
所以,在安迪描述了同样的问题,并要求在Vapor上找到一个解决方案之后,我被重定向到这里。
我对坦纳提出的解决方案的实现(使用PostgreSQL)可以找到这里。
关键是Rating
模型:
Model
子类entity
名称为movie_user
(按字母顺序由坦纳描述相关模型的名称)userId
(映射到"user_id"
)和movieId
(映射到"movie_id"
),两者都属于Node
类型。prepare(Database)
中,它再次使用名称"movie_user"
,并将Id字段定义为Int
的字段。有了这个设置,您就可以定义以下关系方便方法:
在Movie
上:所有评分员
extension Movie {
func raters() throws -> Siblings<User> {
return try siblings()
}
}
在User
上:所有分级电影
extension User {
func ratedMovies() throws -> Siblings<Movie> {
return try siblings()
}
}
电影的新评级(对用户而言)可以如下所示:
ratings.post() { request in
var rating = try Rating(node: request.json)
try rating.save()
return rating
}
因为Rating
是一个Model子类,所以我们可以直接从请求JSON创建它。这要求客户端发送符合Rating
类节点结构的JSON文档:
{
"user_id": <the rating users id>,
"movie_id": <the id of the movie to be rated>,
"stars": <1-5 or whatever makes sense for your usecase>
}
要获得给定电影的所有实际Rating
,您似乎必须手动解决关系(至少我认为是这样的,也许有人可以给我一个更好的提示):
let ratings = try Rating.query().filter("movie_id", movieId).all()
而且,现在似乎无法以某种方式计算数据库的平均值。我会喜欢这样的工作:
// this is now how it works
let averageRating = try Rating.query().filter("movie_id", movieId).average("stars")
所以我希望这对任何遇到这个问题的人都有帮助。感谢所有为Vapor项目做出贡献的优秀人士!
Thx到@WERUreo,因为它指出创建评级的部分丢失了。
https://stackoverflow.com/questions/40565582
复制相似问题