Różnica między filtrem a filter_by w SQLAlchemy

304

Czy ktoś może wyjaśnić różnicę między filteri filter_byfunkcje w SQLAlchemy? Którego powinienem używać?

bodacydo
źródło

Odpowiedzi:

393

filter_by służy do prostych zapytań o nazwy kolumn przy użyciu zwykłych kwargs, takich jak

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

To samo można osiągnąć filter, nie używając kwargs, ale zamiast tego używając operatora równości „==”, który został przeciążony na obiekcie db.users.name:

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

Możesz także pisać bardziej rozbudowane zapytania filter, takie jak wyrażenia takie jak:

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

Daniel Velkov
źródło
22
Jak to działa pod maską? Nie db.users.name=='Ryan'oceniałby raz na stały, a następnie byłby bez znaczenia odtąd? Wydaje się, że aby to zadziałało, trzeba by użyć lambda.
Hamish Grubijan
46
operator równości jest przeciążony
Daniel Velkov
9
type(model.column_name == 'asdf')sqlalchemy.sql.elements.BinaryExpression
Nick T
11
Zachowaj ostrożność podczas korzystania .filter. zapytanie jak id=12345, query(users).filter(id == id)nie będzie filtrować users.id. Zamiast tego oceni id == idjako Truei zwróci wszystkich użytkowników. Musisz użyć .filter(users.id == id)(jak pokazano powyżej). Dzisiaj popełniłem ten błąd.
Nico Cernek
118

Tak naprawdę pierwotnie je scaliliśmy, tzn. Istniała metoda podobna do „filtru”, która zaakceptowała *argsi **kwargs, gdzie można było przekazać wyrażenie SQL lub argumenty słowa kluczowego (lub oba). Uważam, że jest to o wiele wygodniejsze, ale ludzie zawsze byli tym zdezorientowani, ponieważ zwykle wciąż przekraczają różnicę między column == expressioni keyword = expression. Więc podzieliliśmy je.

zzzeek
źródło
30
Myślę, że twoja uwaga na temat column == expressionkontra keyword = expressionjest kluczową kwestią do rozróżnienia między filteri filter_by. Dzięki!
Hollister,
2
Jestem nowy w sqlalchemy, więc przepraszam, jeśli to głupie pytanie, ale filter_by () wydaje się nie dopuszczać nawet bardzo prostych warunków, takich jak „cena> = 100”. Dlaczego więc w ogóle ma funkcję filter_by (), skoro można jej używać tylko w najprostszych warunkach, takich jak „cena = 100”?
PawelRoman
18
bo ludziom się to podoba
zzzeek
3
Czy jest między nimi jakaś różnica w wydajności? Myślałem, że to filter_bymoże być trochę szybsze niż filter.
Devi
6
Chodzi o filter_byto, aby móc napisać jutro nazwę pola, dla tej klasy, bez zadawania pytań - podczas gdy flterwymaga rzeczywistego obiektu kolumny - który zwykle wymaga wpisania (i odczytania) przynajmniej nadmiarowej nazwy klasy. Więc jeśli ktoś chce filtrować według równości, jest to raczej wygodne.
jsbueno
36

filter_byużywa argumentów słów kluczowych, natomiast filterpozwala na filtrowanie argumentów pythonicznych, takich jakfilter(User.name=="john")

Johannes Charra
źródło
34

Jest to cukier składniowy do szybszego pisania zapytań. Jego implementacja w pseudokodzie:

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

Dla AND możesz po prostu napisać:

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

można zapisać jako

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

Możesz także uzyskać obiekt bezpośrednio przez PK getmetodą:

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

W getprzypadku użycia przypadku ważne jest, aby obiekt mógł zostać zwrócony bez żądania bazy danych, z identity mapktórego można go wykorzystać jako pamięć podręczną (powiązaną z transakcją)

enomad
źródło
Te przykłady kodu są mylące: Deklaratywne klasy i instancje tabeli bazowej nie mają metod filtrowania ani zapytań; używają sesji.
Turtles Are Cute
Odtwarzam users.filterz poprzedniej odpowiedzi. I może to być moja wina :) queryatrybut jest zapytanie_property i jest to obecnie dość standardowy cukier
enomad