2014-05-06 20 views
6

Nói rằng tôi có một vài đối tượng, có một-nhiều mối quan hệ, một cái gì đó giống nhưLọc truy vấn SQLAlchemy kết quả của đối tượng thuộc tính 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")) 

Bây giờ, tôi muốn truy vấn đối tượng phụ huynh, nhưng có con cái của họ được lọc bởi child_type, tức là một cái gì đó như

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

Điều này chỉ trả về cho cha mẹ với tất cả trẻ em, về cơ bản không quan tâm đến bộ lọc. Có phải kết quả này có thể xảy ra hay tôi cũng phải truy vấn Child?

Trả lời

0

Bạn cố gắng nhận được hai câu trả lời trong một truy vấn. Hoặc là bạn có thể yêu cầu tất cả các bậc cha mẹ có một loại trẻ em hoặc bạn có thể yêu cầu tất cả các loại trẻ em. Trong trường hợp đầu tiên, bạn phải lọc các trẻ em một lần nữa, nếu bạn muốn các con tương ứng, trong trường hợp thứ hai bạn có thể đơn giản có được cha mẹ tương ứng. Nhưng cách nào là đúng, phụ thuộc vào vấn đề tiếp theo, bạn cố gắng giải quyết.

6

Thật vậy, truy vấn của bạn thêm tham gia và bộ lọc nhưng chỉ trả về Parent trường hợp. Thực tế, chỉ chỉ những trường hợp Parent trường hợp có ít nhất một Child loại a.
Khi bạn truy cập .children trên mỗi cha mẹ đó, một câu lệnh SQL mới sẽ được phát hành và tất cả trẻ em của cha mẹ đó sẽ được tải. Bạn có thể áp dụng lại bộ lọc trong bộ nhớ hoặc tạo truy vấn của riêng bạn và không dựa vào điều hướng mối quan hệ (đã nhận xét) như sau:

Cách để thực hiện trong một truy vấn được hiển thị bên dưới, nhưng hãy cẩn thận khi bạn đang nói hiệu quả sqlalchemy rằng bạn đã tải tất cả trẻ em cho cha mẹ. Bạn có thể sử dụng phương pháp này cho các tình huống nơi bạn thực hiện truy vấn của mình và sau đó hủy/tái chế phiên:

# select all parents, and eager-load children of type "a" 
parents = (session.query(Parent) 
     .join(Parent.children).filter(Child.child_type == "a") 
     # make SA think we loaded all *parent.children* collection 
     .options(contains_eager('children')) 
     ) 

for p in parents: 
    children_a = p.children # now *children* are *incorrectly* filtered 
    print("BBB", p) 
    for c in children_a: 
     print("BBB ..", c) 
Các vấn đề liên quan