Unterschied zwischen filter und filter_by in SQLAlchemy

304

Könnte jemand den Unterschied zwischen filterund filter_byFunktionen in SQLAlchemy erklären ? Welches soll ich verwenden?

bodacydo
quelle

Antworten:

393

filter_by wird für einfache Abfragen der Spaltennamen mit regulären kwargs wie verwendet

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

Dasselbe kann erreicht werden filter, indem nicht kwargs, sondern der Gleichheitsoperator '==' verwendet wird, der für das Objekt db.users.name überladen wurde:

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

Sie können auch leistungsfähigere Abfragen schreiben filter, indem Sie Ausdrücke wie:

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

Daniel Velkov
quelle
22
Wie funktioniert das unter der Haube? Würde man nicht db.users.name=='Ryan'einmal eine Konstante auswerten und dann von da an bedeutungslos sein? Es scheint, als müsste man ein Lambda verwenden, damit dies funktioniert.
Hamish Grubijan
46
Der Gleichstellungsoperator ist überlastet
Daniel Velkov
9
type(model.column_name == 'asdf')sqlalchemy.sql.elements.BinaryExpression
Nick T
11
Seien Sie vorsichtig bei der Verwendung .filter. eine Abfrage wie id=12345, query(users).filter(id == id)wird nicht gefiltert werden users.id. Stattdessen wird es bewerten , id == idwie Trueund alle Benutzer zurück. Sie müssen verwenden .filter(users.id == id)(wie oben demonstriert). Ich habe diesen Fehler heute früher gemacht.
Nico Cernek
118

Wir hatten diese ursprünglich zusammengeführt, dh es gab eine "filter" -ähnliche Methode, die akzeptierte *argsund **kwargsbei der Sie einen SQL-Ausdruck oder Schlüsselwortargumente (oder beides) übergeben konnten. Eigentlich finde ich das viel bequemer, aber die Leute waren immer verwirrt, da sie normalerweise immer noch über den Unterschied zwischen column == expressionund hinwegkommen keyword = expression. Also haben wir sie aufgeteilt.

zzzeek
quelle
30
Ich denke, Ihr Punkt über column == expressionvs. keyword = expressionist der entscheidende Punkt, um den Unterschied zwischen filterund zu machen filter_by. Vielen Dank!
Hollister
2
Ich bin neu in der SQLalchemie. Entschuldigen Sie, wenn dies eine dumme Frage ist, aber filter_by () scheint nicht einmal die sehr einfachen Bedingungen wie "Preis> = 100" zu berücksichtigen. Warum sollte filter_by () überhaupt funktionieren, wenn Sie es nur für die einfachste Bedingung wie "price = 100" verwenden können?
PawelRoman
18
weil die Leute es mögen
zzzeek
3
Gibt es einen Leistungsunterschied zwischen ihnen? Ich dachte, das filter_bykönnte etwas schneller sein als filter.
Devi
6
Der Zweck der Verwendung filter_bybesteht darin, in der Lage zu sein, nur den Feldnamen für diese Klasse zu schreiben, ohne dass Fragen gestellt werden - während flterdas eigentliche Spaltenobjekt erforderlich ist -, für die normalerweise mindestens ein redundanter Klassenname eingegeben (und gelesen) werden muss. Wenn man also nach Gleichheit filtern möchte, ist dies ziemlich praktisch.
Jsbueno
36

filter_byverwendet Schlüsselwortargumente, während filterpythonische Filterargumente wiefilter(User.name=="john")

Johannes Charra
quelle
34

Es ist ein Syntaxzucker für schnelleres Schreiben von Abfragen. Seine Implementierung im Pseudocode:

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

Für UND können Sie einfach schreiben:

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

Übrigens

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

kann geschrieben werden als

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

Sie können das Objekt auch direkt per PK über die folgende getMethode abrufen :

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

Bei Verwendung von getcase ist es wichtig, dass das Objekt ohne Datenbankanforderung zurückgegeben werden kann, von identity mapder aus es als Cache verwendet werden kann (im Zusammenhang mit der Transaktion).

Enomad
quelle
Diese Codebeispiele sind irreführend: Deklarative Basistabellenklassen und -instanzen haben weder Filter- noch Abfragemethoden. Sie nutzen die Sitzung.
Schildkröten sind süß
Ich reproduziere users.filtervon vorheriger Antwort. Und vielleicht ist es meine Schuld :) queryAttribut ist query_property und es ist heutzutage ein ziemlich normaler Zucker
enomad