Vapor 3 和 Fluent - 嵌套查询

Vapor 3 and Fluent - nested query

我正在尝试在 Vapor 3 和 Fluent 中进行嵌套查询。关键是我需要从具有特定 eventID 的每个团队中获取所有用户。团队是 children 个活动。用户是 children 个团队。在此先感谢您的帮助。 每个活动只有 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,我希望它发送给 return 所有团队中的所有用户

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()
        }
    }
}

您可以使用原始 SQL 查询或使用 SwifQL lib

轻松查询

这里有一个 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)
    }
}

这是我在 Ray Wenderlich 的书的帮助下得出的结论。在我的任务中,我不需要 return 所有用户,一次只需要查看 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
}