首页 > 解决方案 > 如何在 SQLAlchemy ORM 中查询多对多关系?

问题描述

我知道这个问题已经被问过好几次了,但没有一个结果有帮助。

我在表格曲目和流派之间有多对多的关系,如下所示:

track_genres = Table('track_genres',
                     Base.metadata,
                     Column('tracks_id', INTEGER, ForeignKey('tracks.id'), primary_key=True),
                     Column('genres_id', INTEGER, ForeignKey('genres.id'), primary_key=True)
                     )

class Genre(Base):
    __tablename__ = 'genres'
    id = Column(INTEGER, primary_key=True, unique=True, autoincrement=True, nullable=False)
    name = Column(TEXT)


class Track(Base):
    __tablename__ = 'tracks'
    id = Column(INTEGER, primary_key=True, unique=True, autoincrement=True, nullable=False)
    name = Column(TEXT)
    album_id = Column(INTEGER, ForeignKey('albums.id'))
    genres = orm.relationship('Genre', secondary=track_genres, backref=orm.backref('tracks', lazy='dynamic',cascade='all'))

据我所知,这些关系是正确声明的,因为我在 track_genres 表中有以下关系:

tracks_id | genres_id
---------------------
1         | 1        
1         | 2        
1         | 3        
1         | 4        
2         | 1        
2         | 2        
2         | 3        
2         | 4        
3         | 5        
3         | 6        
3         | 7        

现在,问题是,当我执行当前查询时

    query = session.query(
        Track,
        Genre.name.label('genre_name')
    ).filter(
        Track.genres.any(id=Genre.id)
    )

我得到一个包含所有数据排列的结果,因此 ID 为 1 的曲目被查询返回 7 次(每个流派 ID 从 1 到 7 一次),即使它应该只返回 4 次(因为ID 为 1 的轨道只有 4 个关系:1-1、1-2、1-3、1-4)

我如何需要在查询中编写我的过滤器/连接,以便查询只返回正确的结果(在这种情况下,对于 ID = 1 的轨道,四行)而不是执行所有可能的排列?

标签: pythonormsqlalchemy

解决方案


经过进一步的实验,我相信正确的方法是从轨道加入各自的关系:

    query = session.query(
        Track,
        Genre.name.label('genre_name')
    ).join.(
        Track.genres
    )


推荐阅读