【问题标题】:Sqlalchemy filter parent and child table for parentsSqlalchemy 为父母过滤父子表
【发布时间】:2020-04-26 15:25:56
【问题描述】:

我有一些模型正在尝试搜索,因此我希望显示返回所有 Parent 对象的结果,其中 Parent 名称为“foo”或 Child 名称为“foo”。

我有疑问:

parents = Session.query(Parent).\
            join(Child_s3).\
            filter(Parent.name.ilike("%foo%")).\
            filter(Child_s3.name.ilike("%foo%")).\
            order_by(asc(Product.name))

还有模特:

class Parent(BaseSO):
    __tablename__ = 'parents'
    id = Column(Integer, primary_key=True)
    name = Column(Unicode(100), nullable=False, unique=True)
    colours = relationship('Child_s3', secondary=Parent_images, backref='Parentc')

class Child_s3(BaseSO):
    __tablename__ = 'children'
    id = Column(Integer, primary_key=True)
    name = Column(Unicode)

Parent_images = Table(
    'Parent_images', BaseSO.metadata,
    Column('parent_id', Integer, ForeignKey('parents.id')),
    Column('child_id', Integer, ForeignKey('children.id'))
)

我的查询显示了名为“foo”的父对象,但没有显示任何父对象,也有名为“foo”的子对象,任何人都可以帮助构建此查询以在两个表中搜索相应的父对象吗?

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    这段代码展示了如何使用显式连接或子查询来获取结果:

    import sqlalchemy as sa
    from sqlalchemy import orm
    from sqlalchemy.ext.declarative import declarative_base
    
    Base = declarative_base()
    
    
    Parent_images = sa.Table(
        'Parent_images', Base.metadata,
        sa.Column('parent_id', sa.Integer, sa.ForeignKey('parents.id')),
        sa.Column('child_id', sa.Integer, sa.ForeignKey('children.id'))
    )
    
    
    class Parent(Base):
        __tablename__ = 'parents'
        id = sa.Column(sa.Integer, primary_key=True)
        name = sa.Column(sa.Unicode(100), nullable=False, unique=True)
        colours = orm.relationship('Child_s3', secondary=Parent_images, backref='parents')
    
        def __repr__(self):
            return 'Parent(name=%s)' % self.name
    
        __str__ = __repr__
    
    
    class Child_s3(Base):
        __tablename__ = 'children'
        id = sa.Column(sa.Integer, primary_key=True)
        name = sa.Column(sa.Unicode)
    
        def __repr__(self):
            return 'Child_s3(name=%s)' % self.name
    
        __str__ = __repr__
    
    
    if __name__ == '__main__':
        engine = sa.create_engine('sqlite:///')
        Base.metadata.drop_all(engine)
        Base.metadata.create_all(engine)
        Session = orm.sessionmaker(bind=engine)
    
        session = Session()
        for parent, child in [('boofoo', 'spam'), ('baz', 'foobar'), ('bar', 'quux')]:
            p1 = Parent(name=parent)
            session.add(p1)
            p1.colours.append(Child_s3(name=child))
        session.commit()
    
        print('Join')
        session = Session()
        q = (session.query(Parent)
                    .join(Child_s3, Parent.colours)
                    .filter(sa.or_(Parent.name.ilike('%foo%'),
                                   Child_s3.name.ilike('%foo%'))))
        for p in q.all():
            print(p, p.colours)
        session.commit()
        print()
    
        print('Subquery')
        session = Session()
        q = (session.query(Parent)
                    .filter(sa.or_(Parent.name.ilike('%foo%'),
                                   Parent.colours.any(Child_s3.name.ilike('%foo%')))))
        for p in q.all():
            print(p, p.colours)
        session.commit()
        print()
    

    连接查询

    q = (session.query(Parent)
                .join(Child_s3, Parent.colours)
                .filter(sa.or_(Parent.name.ilike('%foo%'),
                               Child_s3.name.ilike('%foo%'))))
    

    生成此 SQL

    SELECT parents.id AS parents_id, parents.name AS parents_name 
    FROM parents JOIN "Parent_images" AS "Parent_images_1" ON parents.id = "Parent_images_1".parent_id JOIN children ON children.id = "Parent_images_1".child_id 
    WHERE lower(parents.name) LIKE lower(?) OR lower(children.name) LIKE lower(?)
    

    子查询

    q = (session.query(Parent)
                .filter(sa.or_(Parent.name.ilike('%foo%'),
                                Parent.colours.any(Child_s3.name.ilike('%foo%')))))
    

    生成此 SQL:

    SELECT parents.id AS parents_id, parents.name AS parents_name            
    FROM parents                                                                                                                        
    WHERE lower(parents.name) LIKE lower(?) OR (EXISTS (SELECT 1                                                                        
    FROM "Parent_images", children                                                                                                      
    WHERE parents.id = "Parent_images".parent_id AND children.id = "Parent_images".child_id AND lower(children.name) LIKE lower(?)))
    

    脚本从示例数据中生成以下输出:

    Join
    Parent(name=baz) [Child_s3(name=foobar)]
    Parent(name=boofoo) [Child_s3(name=spam)]
    
    Subquery
    Parent(name=boofoo) [Child_s3(name=spam)]
    Parent(name=baz) [Child_s3(name=foobar)]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-07
      • 2021-08-24
      • 1970-01-01
      • 1970-01-01
      • 2015-08-19
      • 2015-02-23
      • 2018-10-10
      • 2019-02-03
      相关资源
      最近更新 更多