【问题标题】:How to do two JOIN query from the same table in Vapor 3 using Fluent?如何使用 Fluent 从 Vapor 3 中的同一个表中进行两个 JOIN 查询?
【发布时间】:2019-01-27 00:16:02
【问题描述】:

这就是我想做的(使用 postgresql):

选择 H."name", A."name"

来自“匹配”M

加入“团队”H ON M."homeTeamID" = H.id

加入“团队”A ON M."awayTeamID" = A.id

//This will give me an error

return Matches.query(on: request)
.join(\Teams.id, to: \Matches.homeTeamID)
.alsoDecode(Teams.self)
.join(\Teams.id, to: \Matches.awayTeamID)
.alsoDecode(Teams.self)

这是错误:

{

错误:是的,

原因:“表名“团队”指定了多次”

}

感谢任何帮助!谢谢!

【问题讨论】:

    标签: postgresql fluent vapor


    【解决方案1】:

    感谢这是一个老问题,但我有一个类似的问题,我通过使用原始 SQL 查询用另一种方法解决了它。

    下面将为主队和客队名称添加额外的列。您需要创建一个 MatchObject 来解码结果并根据您的具体情况建立连接。

    func matchObjects(_ req: Request) throws -> Future<[MatchObject]> {
        return req.withPooledConnection(to: .psql, closure: { conn in
                    return conn.raw("""
                        SELECT "Matches".*, h.name as home_team_name, a.name as away_team_name
                        FROM "Matches"
                        INNER JOIN "Teams" as h ON "Matches"."homeTeamID" = h.id
                        INNER JOIN "Teams" as a ON "Matches"."awayTeamID" = a.id
                        """).all(decoding: MatchObject.self)
                })
    }
    

    【讨论】:

      【解决方案2】:

      我在这里创建了一个测试项目: https://github.com/mixio/multi-join-test

      【讨论】:

      • 太棒了!谢谢!
      【解决方案3】:

      @arema,我试图重现您的用例,并且在 Fluent 中遇到了类似的问题。 我在 Fluent 的 github 上报告了这个问题: https://github.com/vapor/fluent/issues/563

      这是一种解决方法,但它远非优雅。

      // Requires conforming `Match` to hashable, Equatable.
      func getMatches2Handler(_ req: Request) throws -> Future<[MatchObjects]> {
          return map(
              to: [MatchObjects].self,
              Match.query(on: req).join(\Team.id, to: \Match.homeTeamID).alsoDecode(Team.self).all(),
              Match.query(on: req).join(\Team.id, to: \Match.awayTeamID).alsoDecode(Team.self).all()
          ) { homeTuples, awayTuples in
              let homeDictionary = homeTuples.toDictionary()
              let awayDictionary = awayTuples.toDictionary()
              var matchObjectsArray: [MatchObjects] = []
              matchObjectsArray.reserveCapacity(homeDictionary.count)
              for (match, homeTeam) in homeDictionary {
                  let awayTeam = awayDictionary[match]!
                  matchObjectsArray.append(MatchObjects(match: match, homeTeam: homeTeam, awayTeam: awayTeam))
              }
              return matchObjectsArray
          }
      }
      
      //...
      
      extension Array {
          func toDictionary<K,V>() -> [K:V] where Iterator.Element == (K,V) {
              return self.reduce([:]) {
                  var dict:[K:V] = $0
                  dict[$1.0] = $1.1
                  return dict
              }
          }
      }
      

      【讨论】:

      • 感谢您尝试并提供解决方法。我试试看。
      猜你喜欢
      • 2019-04-01
      • 1970-01-01
      • 2014-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-08
      相关资源
      最近更新 更多