Flask Sqlalchemy - 使用多个值查询多对多

Flask Sqlalchemy - query many to many with several values

我在比赛和球队之间有一个多对多的关系,一场比赛可以有多个球队参加,每个球队可以有不止一场比赛。模型是:

class Match(db.Model):
    __tablename__ = 'match'

    id = Column(
        db.Integer,
        primary_key=True,
        autoincrement=True)

    teams = db.relationship('Team', secondary='team_match_link')

class Team(db.Model):
    __tablename__ = 'team'

    id = Column(
        db.Integer,
        primary_key=True,
        autoincrement=True)

    matches = db.relationship('Match', secondary='team_match_link')


class TeamMatchLink(db.Model):

    __tablename__ = 'team_match_link'

    match_id = Column(
        db.Integer,
        db.ForeignKey('match.id'),
        primary_key=True
    )

    team_id = Column(
        db.Integer,
        db.ForeignKey('team.id'),
        primary_key=True
    )

给定两支球队 [T1, T2],我如何查询完全包含这两支球队而没有其他球队的比赛?

这给了我至少包含两支球队的比赛,然后我当然可以检查这些比赛中是否还有其他球队。但它看起来很难看,我确定有 better/more 有效的方法?理想情况下,该解决方案应该适用于 n 个团队,而不会让我陷入困境。

res1 = match.query.filter(match.team.any(id=T1.id)).all()
res2 = match.query.filter(match.team.any(id=T2.id)).all()
res = [i for i in res1 if i in res2]

查询比赛队伍 links 并通过统计条目数进行聚合。

下面的查询和一些解释:

your_teams = [T1.id, T2.id]
result = db.session.query(Match, TeamMatchLink).filter(TeamMatchLink.team_id.in_(your_teams)).group_by(TeamMatchLink.match_id).having(func.count(TeamMatchLink.team_id) == len(your_teams)).join(Match).all()

查询由几个部分和想法串在一起:

team_link_query = db.session.query(TeamMatchLink).filter(TeamMatchLink.team_id.in_(your_teams)))

这将选择包含您想要的团队的所有团队 link。

applicable_matches_query = team_link_query.group_by(TeamMatchLink.match_id).having(func.count(TeamMatchLink.team_id) == len(your_teams))

这会聚合团队匹配 link 以查找包含您需要的所有团队的匹配。 (一场比赛将出现 nr 次,球队 link 将与 your_teams 列表匹配)

最后,加入将为您匹配。您当然可以减少查询,只为您直接提供来自团队比赛 link table 的比赛 ID。