过滤SQLAlchemy查询结果对象的一对多属性

时间:2014-05-06 21:31:03

标签: python orm sqlalchemy filtering one-to-many

说我有几个对象,有一对多的关系,比如

class Parent():
    //id, other cols, etc
    children = relationship("Child", backref="parent")

class Child():
    parent_id = Column(Integer, ForeignKey("parent.id")
    child_type = Column(Enum("a","b"))

现在,我想查询Parent对象,但让他们的子进程按child_type过滤,即

session.query(Parent).join(Parent.children).filter(Child.child_type == "a")

这只会返回包含所有子节点的Parent,基本上忽略了过滤器。这个结果是否完全可能,还是我还要查询Child?

2 个答案:

答案 0 :(得分:7)

实际上,您的查询会添加连接和过滤器,但只返回Parent个实例。事实上,那些至少有Parent类型为Child的{​​{1}}个实例。
然后,当您在每个父项上访问a时,将发出新的SQL语句,并且将加载该父项的所有子项。您可以在内存中再次应用过滤器,或创建自己的查询,而不是依赖关系导航(注释掉),如下所示:

.children

下面显示了在一个查询中执行此操作的方法,但要小心,因为您有效地告诉sqlalchemy您为父母加载了所有子项。您可以在执行查询的场景中使用此方法,然后丢弃/回收会话:

# select *only* those parents who have at least one child of type "a"
parents = session.query(Parent).join(Parent.children).filter(Child.child_type == "a")
for p in parents:
    # 1. in-memory filter: now select only type "a" children for each parent
    children_a = [c for c in p.children if c.child_type == 'a']
    # 2. custom query: now select only type "a" children for each parent
    # children_a = session.query(Child).with_parent(p).filter(Child.child_type == "a")

    print("AAA", p)
    for c in children_a:
        print("AAA ..", c)

答案 1 :(得分:1)

您尝试在一个查询中获得两个答案。你可以要求所有有孩子类型的父母,或者你可以要求所有类型的孩子。在第一种情况下,如果需要相应的子项,则必须再次过滤子项,在第二种情况下,您可以简单地获取相应的父项。但是哪种方式是正确的,取决于进一步的问题,你试图解决。