如何使用Fluent在Vapor 3的同一张表中进行两个JOIN查询?

时间:2018-08-20 20:21:12

标签: postgresql fluent vapor

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

选择H.“名称”,A。“名称”

FROM“匹配” M

加入“团队” H ONM。“ homeTeamID” = H.id

在M上加入“团队”A。“ awayTeamID” = A.id

CloughTocher2DInterpolator

这是错误:

{

错误:是,

原因:“表名称“ Teams”指定了多次”

}

感谢您的帮助!谢谢!

3 个答案:

答案 0 :(得分:1)

@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
        }
    }
}

答案 1 :(得分:0)

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

答案 2 :(得分:0)

现在意识到这是一个古老的问题,但是我遇到了类似的问题,我通过使用原始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)
            })
}