Perbedaan antara filter dan filter_by dalam SQLAlchemy

304

Adakah yang bisa menjelaskan perbedaan antara filterdan filter_byfungsi dalam SQLAlchemy? Yang mana yang harus saya gunakan?

bodacydo
sumber

Jawaban:

393

filter_by digunakan untuk pertanyaan sederhana pada nama kolom menggunakan kwarg biasa, seperti

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

Hal yang sama dapat dilakukan dengan filter, tidak menggunakan kwargs, melainkan menggunakan operator persamaan '==', yang telah kelebihan beban pada objek db.users.name:

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

Anda juga dapat menulis kueri yang lebih kuat menggunakan filter, seperti ekspresi seperti:

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

Daniel Velkov
sumber
22
Bagaimana cara kerjanya di bawah tenda? Tidak akan db.users.name=='Ryan'mengevaluasi sekali ke konstanta dan kemudian menjadi tidak berarti sejak saat itu? Sepertinya orang perlu menggunakan lambda agar ini berfungsi.
Hamish Grubijan
46
operator kesetaraan kelebihan beban
Daniel Velkov
9
type(model.column_name == 'asdf')sqlalchemy.sql.elements.BinaryExpression
Nick T
11
Hati-hati saat menggunakan .filter. kueri seperti id=12345, query(users).filter(id == id)tidak akan difilter users.id. Sebaliknya, ia akan mengevaluasi id == idsebagai Truedan mengembalikan semua pengguna. Anda perlu menggunakan .filter(users.id == id)(seperti yang ditunjukkan di atas). Saya membuat kesalahan ini sebelumnya hari ini.
Nico Cernek
118

Kami sebenarnya menggabungkan ini bersama-sama pada awalnya, yaitu ada metode "filter" yang diterima *argsdan **kwargs, di mana Anda dapat menyampaikan argumen SQL atau argumen kata kunci (atau keduanya). Sebenarnya saya merasa jauh lebih nyaman, tetapi orang-orang selalu bingung karenanya, karena mereka biasanya masih bisa mengatasi perbedaan antara column == expressiondan keyword = expression. Jadi kami membaginya.

zzzeek
sumber
30
Saya pikir poin Anda tentang column == expressionvs keyword = expressionadalah poin kunci untuk membuat perbedaan antara filterdan filter_by. Terima kasih!
Hollister
2
Saya baru mengenal sqlalchemy jadi maafkan saya jika ini adalah pertanyaan bodoh, tetapi filter_by () tampaknya tidak memungkinkan bahkan untuk kondisi yang sangat sederhana seperti "harga> = 100". Jadi, mengapa memiliki fungsi filter_by (), jika Anda hanya dapat menggunakannya untuk kondisi yang paling sederhana seperti "price = 100"?
PawelRoman
18
karena orang-orang menyukainya
zzzeek
3
Apakah ada perbedaan kinerja di antara mereka? Saya berpikir bahwa filter_bymungkin sedikit lebih cepat daripada filter.
Devi
6
Maksud dari penggunaannya filter_byadalah untuk dapat menulis menjorok nama bidang, untuk kelas itu, tidak ada pertanyaan yang diajukan - sementara fltermembutuhkan objek kolom yang sebenarnya - yang biasanya akan membutuhkan satu untuk mengetik (dan membaca) setidaknya nama kelas yang berlebihan. Jadi, jika seseorang ingin menyaring berdasarkan kesetaraan, itu lebih mudah.
jsbueno
36

filter_bymenggunakan argumen kata kunci, sedangkan filtermemungkinkan argumen penyaringan pythonic sukafilter(User.name=="john")

Johannes Charra
sumber
34

Ini adalah gula sintaks untuk penulisan kueri yang lebih cepat. Implementasinya dalam pseudocode:

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

Untuk DAN Anda cukup menulis:

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'))

dapat ditulis sebagai

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

Anda juga bisa mendapatkan objek secara langsung dengan PK melalui getmetode:

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

Ketika menggunakan getcase, penting bahwa objek dapat dikembalikan tanpa permintaan basis data identity mapyang dapat digunakan sebagai cache (terkait dengan transaksi)

enomad
sumber
Contoh kode ini menyesatkan: Kelas dan instance tabel dasar deklaratif tidak memiliki metode filter atau kueri; mereka menggunakan sesi.
Turtles Are Cute
Saya mereproduksi users.filterdari jawaban sebelumnya. Dan mungkin itu salahku :) queryatribut adalah query_property dan gula yang cukup standar saat ini
enomad