Vapor 3 和 Fluent - 嵌套查询
Posted
技术标签:
【中文标题】Vapor 3 和 Fluent - 嵌套查询【英文标题】:Vapor 3 and Fluent - nested query 【发布时间】:2019-12-09 21:41:24 【问题描述】:我正在尝试在 Vapor 3 和 Fluent 中进行嵌套查询。关键是我需要从每个团队拥有特定 eventID 的团队中获取所有用户。团队是 Event 的子代。用户是 Teams 的子级。在此先感谢您的帮助。 每个活动只有 15 个团队,但每个团队有 12 个用户
这里是事件模型:
final class Event: Codable
var id: Int?
var name: String
extension Event
var teams: Children<Event, Team>
return children(\.eventID)
这是团队模型
final class Team: Codable
var id: Int?
var name: String
var icon: String
var eventID: Event.ID
extension Team
var user: Parent<Team, Event>
return parent(\.eventID)
extension Team
var users: Children<Team, User>
return children(\.teamID)
这是用户模型。
final class User: Codable
var id: UUID?
var name: String
var email: String
var eventID: Event.ID
var teamID: Team.ID
extension User
var user: Parent<User, Team>
return parent(\.teamID)
我需要发送一个事件 ID,我希望它返回所有团队中的所有用户
func getUsersForEvent(_ req: Request) throws -> Future<[User]>
return try req.parameters.next(Event.self).flatMap(to: [User].self) event in
return try event.teams.query(on: req).all().flatMap(to: [User].self) team in
return try team.users.query(on: req).all()
【问题讨论】:
【参考方案1】:您可以使用原始 SQL 查询或使用 SwifQL 库轻松查询
这是一个使用 SwifQL 的示例
struct TeamWithUsers: Content
let id: UUID
let name, icon: String
let users: [User]
func getCategoriesWithProducts(_ req: Request) throws -> Future<[TeamWithUsers]>
return try req.parameters.next(Event.self).flatMap event in
let usersSubquery = SwifQL
.select(Fn.coalesce(Fn.array_agg(Fn.to_jsonb(User.table)), PgArray() => .jsonbArray))
.from(User.table)
.where(\User.teamID == \Team.id)
let query = try SwifQL
.select(\Team.id, \Team.name, \Team.icon, |usersSubquery | => "users")
.from(Team.table)
.where(\Team.eventID == event.requireID())
// here you could print the raw query for debugging
// print(query.prepare(.psql).plain)
return query.execute(on: req, as: .psql).all(decoding: TeamWithUsers.self)
【讨论】:
【参考方案2】:在 Ray Wenderlich 的书的帮助下,这是我的想法。在我的任务中,我不需要返回所有用户,一次只需要查看 1 个事件的团队,因此我将 eventID 作为参数传递。
关于如何按 teamScore 对结果进行排序的任何指导?
func getTeamsWithUsersForEvent(_ req: Request) throws -> Future<[TeamWithUsers]>
let currentID = try req.parameters.next(Int.self)
print("currentID \(currentID)")
return Team.query(on: req).filter(\Team.eventID == currentID).all().flatMap(to: [TeamWithUsers].self) team in
try team.map team in
try team.users.query(on: req).all().map users in
TeamWithUsers(
id: team.id,
name: team.name,
icon: team.icon,
eventID: team.eventID,
//rawScore: team.rawScore,
//users: users,
count: users.count,
teamScore: team.rawScore / users.count
)
.flatten(on: req)
struct TeamWithUsers: Content
let id: Int?
let name: String
let icon: String
let eventID: Event.ID
//let rawScore: Int
//let users: [User]
let count: Int
let teamScore: Int
【讨论】:
以上是关于Vapor 3 和 Fluent - 嵌套查询的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Vapor/Fluent 中正确查询 Postgres JSONB 字段