SqlAlchemy - Lọc theo thuộc tính mối quan hệ


94

Tôi không có nhiều kinh nghiệm với SQLAlchemy và tôi gặp sự cố mà tôi không thể giải quyết. Tôi đã thử tìm kiếm và tôi đã thử rất nhiều mã. Đây là Lớp của tôi (được giảm xuống mã quan trọng nhất):

class Patient(Base):
    __tablename__ = 'patients'
    id = Column(Integer, primary_key=True, nullable=False)
    mother_id = Column(Integer, ForeignKey('patients.id'), index=True)
    mother = relationship('Patient', primaryjoin='Patient.id==Patient.mother_id', remote_side='Patient.id', uselist=False)
    phenoscore = Column(Float)

và tôi muốn truy vấn tất cả bệnh nhân có chỉ số phenoscore của mẹ (ví dụ) == 10

Như đã nói, tôi đã thử rất nhiều mã, nhưng tôi không nhận được nó. Giải pháp hợp lý, trong mắt tôi, sẽ là

patients = Patient.query.filter(Patient.mother.phenoscore == 10)

bởi vì, bạn có thể truy cập .mother.phenoscorecho từng phần tử khi xuất ra, nhưng mã này không làm điều đó.

Có khả năng (trực tiếp) để lọc theo một thuộc tính của một mối quan hệ (mà không cần viết Câu lệnh SQL hoặc một câu lệnh kết hợp bổ sung) không, tôi cần loại bộ lọc này nhiều lần.

Ngay cả khi không có giải pháp dễ dàng, tôi rất vui khi nhận được tất cả các câu trả lời.

Câu trả lời:


169

Sử dụng phương pháp has()quan hệ (đọc thêm):

patients = Patient.query.filter(Patient.mother.has(phenoscore=10))

hoặc tham gia (thường nhanh hơn):

patients = Patient.query.join(Patient.mother, aliased=True)\
                    .filter_by(phenoscore=10)

9
bệnh nhân = Patient.query.filter (Patient.mother.has (Patient.phenoscore == 10))
user1105851

@ user1105851 has()hỗ trợ cả biểu thức điều kiện dưới dạng đối số không tên và filter_byđối số từ khóa kiểu. Càng về sau có vẻ dễ đọc hơn đối với tôi.
Denis Otkidach 19/12/11

@DenisOtkidach đúng, nhưng sau đó sẽ như vậy phenoscore = 10. filter_bychỉ lấy các từ khóa bình đẳng (vì nó chỉ làm ** kwargs trên chúng)
aruisdante

@aruisdante Bạn nói đúng, câu trả lời đã được chỉnh sửa sai.
Denis Otkidach

4
sử dụng bất kỳ thay vì: bệnh nhân = Patient.query.filter (Patient.mother.any (phenoscore = 10))
Boston Kenne


7

Tôi đã sử dụng nó với các phiên, nhưng một cách thay thế mà bạn có thể truy cập trực tiếp vào trường mối quan hệ là

db_session.query(Patient).join(Patient.mother) \
    .filter(Patient.mother.property.mapper.class_.phenoscore==10)

Tôi chưa thử nghiệm nó, nhưng tôi đoán điều này cũng sẽ hoạt động

Patient.query.join(Patient.mother) \
    .filter(Patient.mother.property.mapper.class_.phenoscore==10)

5

Tin tốt cho bạn: Gần đây tôi đã tạo gói cung cấp cho bạn tính năng lọc / sắp xếp với các chuỗi "ma thuật" như trong Django , vì vậy bây giờ bạn có thể viết một cái gì đó như

Patient.where(mother___phenoscore=10)

Nó ngắn hơn rất nhiều, đặc biệt là đối với các bộ lọc phức tạp,

Comment.where(post___public=True, post___user___name__like='Bi%')

Hy vọng bạn sẽ thích gói này

https://github.com/absent1706/sqlalchemy-mixins#django-like-queries


0

Đây là câu trả lời tổng quát hơn về cách truy vấn mối quan hệ.

relationship(..., lazy='dynamic', ...)

Điều này cho phép bạn:

parent_obj.some_relationship.filter(ParentClass.some_attr==True).all()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.