Sự khác biệt giữa bộ lọc và bộ lọc_by trong SQLAlchemy


304

Bất cứ ai cũng có thể giải thích sự khác biệt giữa filtervà các filter_bychức năng trong SQLAlchemy? Tôi nên sử dụng cái nào?

Câu trả lời:


393

filter_by được sử dụng cho các truy vấn đơn giản trên các tên cột bằng cách sử dụng các kwarg thông thường, như

db.users.filter_by(name='Joe')

Điều tương tự có thể được thực hiện với filter, không sử dụng kwargs, mà thay vào đó là sử dụng toán tử đẳng thức '==', đã bị quá tải trên đối tượng db.users.name:

db.users.filter(db.users.name=='Joe')

Bạn cũng có thể viết các truy vấn mạnh hơn bằng cách sử dụng filter, chẳng hạn như các biểu thức như:

db.users.filter(or_(db.users.name=='Ryan', db.users.country=='England'))


22
Làm thế nào để làm việc này dưới mui xe? Sẽ không db.users.name=='Ryan'đánh giá một lần đến một hằng số và sau đó là vô nghĩa? Có vẻ như người ta sẽ cần sử dụng lambda để làm việc này.
Hamish Grubijan

46
toán tử bình đẳng bị quá tải
Daniel Velkov

9
type(model.column_name == 'asdf')sqlalchemy.sql.elements.BinaryExpression
Nick T

11
Cẩn thận khi sử dụng .filter. một truy vấn như thế id=12345, query(users).filter(id == id)sẽ không lọc users.id. Thay vào đó, nó sẽ đánh giá id == idnhư Truevà gửi lại tất cả người dùng. Bạn cần sử dụng .filter(users.id == id)(như demo ở trên). Tôi đã phạm sai lầm này sớm hơn ngày hôm nay.
Nico Cernek

118

Chúng tôi thực sự đã có những thứ này được hợp nhất với nhau ban đầu, tức là có một phương thức giống như "bộ lọc" được chấp nhận *args**kwargs, nơi bạn có thể chuyển một biểu thức SQL hoặc đối số từ khóa (hoặc cả hai). Tôi thực sự thấy rằng thuận tiện hơn rất nhiều, nhưng mọi người luôn bối rối vì nó, vì họ vẫn thường vượt qua sự khác biệt giữa column == expressionkeyword = expression. Vì vậy, chúng tôi chia chúng ra.


30
Tôi nghĩ rằng quan điểm của bạn về column == expressionso với keyword = expressionlà điểm quan trọng để tạo ra sự khác biệt giữa filterfilter_by. Cảm ơn!
Hollister

2
Tôi chưa quen với sqlalchemy, xin lỗi nếu đây là một câu hỏi ngu ngốc, nhưng bộ lọc_by () dường như không cho phép ngay cả những điều kiện rất đơn giản như "price> = 100". Vì vậy, tại sao vẫn có hàm filter_by (), nếu bạn chỉ có thể sử dụng nó cho điều kiện rất đơn giản nhất như "price = 100"?
PawelRoman

18
bởi vì mọi người thích nó
zzzeek

3
Có sự khác biệt hiệu suất giữa chúng? Tôi đã nghĩ rằng filter_bycó thể nhanh hơn một chút filter.
Devi

6
Điểm quan trọng của việc sử dụng filter_bylà có thể viết tên trường, cho lớp đó, không có câu hỏi nào được hỏi - trong khi flteryêu cầu đối tượng cột thực tế - thường sẽ yêu cầu một người gõ (và đọc) ít nhất một tên lớp dự phòng. Vì vậy, nếu một người muốn lọc theo đẳng thức, nó khá thuận tiện.
jsbueno

36

filter_bysử dụng các đối số từ khóa, trong khi filtercho phép các đối số lọc pythonic nhưfilter(User.name=="john")


34

Nó là một cú pháp đường để viết truy vấn nhanh hơn. Nó thực hiện trong mã giả:

def filter_by(self, **kwargs):
    return self.filter(sql.and_(**kwargs))

Đối với AND bạn chỉ có thể viết:

session.query(db.users).filter_by(name='Joe', surname='Dodson')

btw

session.query(db.users).filter(or_(db.users.name=='Ryan', db.users.country=='England'))

có thể được viết như

session.query(db.users).filter((db.users.name=='Ryan') | (db.users.country=='England'))

Ngoài ra, bạn có thể lấy đối tượng trực tiếp bằng PK thông qua getphương thức:

Users.query.get(123)
# And even by a composite PK
Users.query.get(123, 321)

Khi sử dụng gettrường hợp quan trọng, đối tượng đó có thể được trả về mà không cần yêu cầu cơ sở dữ liệu từ identity mapđó có thể được sử dụng làm bộ đệm (liên kết với giao dịch)


Các ví dụ mã này là sai lệch: Các lớp và trường hợp bảng cơ sở khai báo không có bộ lọc cũng như các phương thức truy vấn; họ sử dụng phiên.
Rùa dễ thương

Tôi sao chép users.filtertừ câu trả lời trước. Và có thể đó là lỗi của tôi :) querythuộc tính là query_property và hiện tại nó là một loại đường tiêu chuẩn
enomad
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.