【问题标题】:Vapor 3 and Fluent - nested queryVapor 3 和 Fluent - 嵌套查询
【发布时间】: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()
        }
    }
}

【问题讨论】:

    标签: vapor vapor-fluent


    【解决方案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
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-11-24
        • 2021-10-25
        • 2019-04-01
        • 2019-07-22
        • 2023-03-22
        • 1970-01-01
        • 2018-12-28
        相关资源
        最近更新 更多