Hi Mike! Thanks for answering. In fact i tried that same code as you posted and it did eager load of original (not my subquery) data. However, here <https://kite.com/docs/python;sqlalchemy.orm.contains_eager> i found a mention that contains_eager has an alias parameter, so doing s.query(A).join(all_b).options(contains_eager(A.b, alias=all_b)).all() helped.
Thanks for helping sort that out! Anatoly On Thursday, 30 November 2017 18:22:06 UTC+3, Mike Bayer wrote: > > On Thu, Nov 30, 2017 at 8:41 AM, Анатолий Иванов <dwh....@gmail.com > <javascript:>> wrote: > > Hello everyone! > > > > > > TL;DR: > > A mapping (class A) has a relationship(to class B). Lazy load is > specified. > > I want to > > > > manually select and filter data from B (the result lets call B') > > select everything from A > > outer join A with B' > > > > Problem: when doing > > > > all_b = session.query(B).filter(B.value == 1).subquery() > > all_a = session.query(A).join(all_b).all() > > > > it performs correct SQL request, although, when accessing all_a.b > performs > > an extra SQL request and selects all B (not B'). How do i make select > with > > the joined data from my subquery instead of selecting whole data from > the > > database? > > > you need to use contains_eager() for that: > > s.query(A).join(all_b).options(contains_eager(A.b)).all() > > docs at > http://docs.sqlalchemy.org/en/latest/orm/loading_relationships.html?highlight=contains_eager#contains-eager > > > > > > > > > Long with working code: > > > > I do some kind of scanner management. Each IP can have several open > ports. > > > > import datetime > > from sqlalchemy import create_engine > > from sqlalchemy.orm import sessionmaker > > from sqlalchemy.pool import NullPool > > from sqlalchemy.orm import aliased, joinedload > > > > from sqlalchemy.orm import relationship > > from sqlalchemy.ext.declarative import declarative_base > > from sqlalchemy import Column, String, ForeignKey, Table, Integer, > DateTime > > > > > > Base = declarative_base() > > > > association_table = Table( > > '_association', Base.metadata, > > Column('ip_id', Integer, ForeignKey('_ips.ip_id')), > > Column('host_id', Integer, ForeignKey('_hosts.host_id')) > > ) > > > > class Sessions(object): > > > > def __init__(self): > > self.engine = create_engine('postgresql://127.0.0.1/black', > > poolclass=NullPool, echo=True) > > self.session_builder = sessionmaker(bind=self.engine, > > expire_on_commit=False) > > > > def get_new_session(self): > > session = self.session_builder() > > > > return session > > > > def destroy_session(self, session): > > session.close() > > > > class IPDatabase(Base): > > __tablename__ = '_ips' > > > > ip_id = Column(Integer, primary_key=True, autoincrement=True) > > > > # The hostnames that point to this IP > > hostnames = relationship( > > "HostDatabase", > > secondary=association_table, > > back_populates="ip_addresses", > > lazy='select' > > ) > > > > # Open ports > > ports = relationship('PortDatabase', cascade="all, delete-orphan", > > lazy='select') > > date_added = Column(DateTime, default=datetime.datetime.utcnow) > > > > def __repr__(self): > > return """ IP=(id={}, ports={}) """.format(self.ip_id, > self.ports) > > > > > > class PortDatabase(Base): > > __tablename__ = '_ports' > > > > ports_id = Column(Integer, primary_key=True, autoincrement=True) > > > > data = Column(String) > > port_number = Column(Integer) > > > > date_added = Column(DateTime, default=datetime.datetime.utcnow) > > > > > > # The name of the related project > > target = Column( > > Integer, ForeignKey('_ips.ip_id', ondelete='CASCADE') > > ) > > > > > > def __repr__(self): > > return """ Port=(id={}, port={}) """.format(self.ports_id, > > self.port_number) > > > > > > def create(): > > sessions = Sessions() > > > > Base.metadata.drop_all(sessions.engine) > > Base.metadata.create_all(sessions.engine, checkfirst=True) > > > > session_spawner = Sessions() > > session = session_spawner.get_new_session() > > > > ip_1 = IPDatabase() > > ip_2 = IPDatabase() > > ip_3 = IPDatabase() > > > > port_1 = PortDatabase(port_number=80) > > port_2 = PortDatabase(port_number=80) > > port_3 = PortDatabase(port_number=443) > > > > ip_1.ports.append(port_1) > > ip_1.ports.append(port_2) > > ip_1.ports.append(port_3) > > > > session.add(ip_1) > > session.add(ip_2) > > session.add(ip_3) > > > > session.add(port_1) > > session.add(port_2) > > session.add(port_3) > > > > session.commit() > > > > session_spawner.destroy_session(session) > > > > def main(): > > session_spawner = Sessions() > > session = session_spawner.get_new_session() > > > > subq = session.query(PortDatabase).filter(PortDatabase.port_number > == > > 80).subquery() > > > > ips = session.query(IPDatabase).join(subq).all() > > > > session_spawner.destroy_session(session) > > > > print(ips) # This will fail, as 'ports' were not loaded due to > > lazyload='select' > > > > if __name__ == '__main__': > > main() > > > > > > Any help would be really great, as i have read tons of manuals and other > > resources, but still cannot find the solution. > > > > Thanks, > > Anatoly > > > > -- > > SQLAlchemy - > > The Python SQL Toolkit and Object Relational Mapper > > > > http://www.sqlalchemy.org/ > > > > To post example code, please provide an MCVE: Minimal, Complete, and > > Verifiable Example. See http://stackoverflow.com/help/mcve for a full > > description. > > --- > > You received this message because you are subscribed to the Google > Groups > > "sqlalchemy" group. > > To unsubscribe from this group and stop receiving emails from it, send > an > > email to sqlalchemy+...@googlegroups.com <javascript:>. > > To post to this group, send email to sqlal...@googlegroups.com > <javascript:>. > > Visit this group at https://groups.google.com/group/sqlalchemy. > > For more options, visit https://groups.google.com/d/optout. > -- SQLAlchemy - The Python SQL Toolkit and Object Relational Mapper http://www.sqlalchemy.org/ To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description. --- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.