简体   繁体   中英

Purpose of joining tables in SQLAlchemy

I'm currently switching from raw SQL queries to the SQLAlchemy package and I'm wondering when to join there tables.

I have 3 tables. Actor and movie are in a M:N relationship. Actor_Movie is the junction table:

class Actor(Base):
    __tablename__ = 'actor'

    act_id = Column(Integer, primary_key=True)
    last_name = Column(String(150), nullable=False, index=True)
    first_name = Column(String(150), nullable=False, index=True)
    movies = relationship('Movie', secondary='actor_movie')

    def __init__(self, last_name, first_name):
        self.last_name = last_name
        self.first_name = first_name

class Movie(Base):
    __tablename__ = 'movie'

    movie_id = Column(Integer, primary_key=True)
    title = Column(String(150))
    actors = relationship('Actor', secondary='actor_movie')

    def __init__(self, title):
        self.title = title

class ActorMovie(Base):
    __tablename__ = 'actor_movie'

    fk_actor_id = Column(Integer, ForeignKey('actor.act_id'), primary_key=True)
    fk_movie_id = Column(Integer, ForeignKey('movie.movie_id'), primary_key=True)

    def __init__(self, fk_actor_id, fk_movie_id):
        self.fk_actor_id = fk_actor_id
        self.fk_movie_id = fk_movie_id

When I write a simple query like:

result = session.query(Movie).filter(Movie.title == 'Terminator').first()

I get the Movie Object back with and actor field. This actor field contains an InstrumentedList with all actors that are related to the film. This seems like a lot overhead when the relationships are always joined.

Why is the relationship automatically populated and when do I need a manual join? Based on the result I'm not even sure if the junction table is correct. This seems to be the most "raw SQL" way. I also saw alternative approaches ie:

Official SQLAlchemy documentation

"This seems like a lot overhead when the relationships are always joined."

They are not. By default relationships perform a select the first time they are accessed — so called lazy loading.

"Why is the relationship automatically populated"

It was accessed on an instance and the relationship is using default configuration.

"...and when do I need a manual join?"

If you need to for example filter the query based on the related table, or you are fetching many movies and know beforehand that you will need all or some of their actors, though for a many to many relationship selectin eager loading may perform better than a join.

"Based on the result I'm not even sure if the junction table is correct."

That is the correct approach. SQLAlchemy is an ORM, and relationship attributes are the object side of the mapping and association/junction tables the relational side.

All in all the purposes are much the same as in raw SQL, but the ORM handles joins under the hood in some cases, such as eager loading, if configured or instructed to do so. As they say on the home page:

SQLAlchemy is the Python SQL toolkit and Object Relational Mapper that gives application developers the full power and flexibility of SQL.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM