sqlalchemy filtert mehrere Spalten

81

Wie kombiniere ich zwei Spalten und wende Filter an? Zum Beispiel möchte ich gleichzeitig in den Spalten "Vorname" und "Nachname" suchen. So habe ich es gemacht, wenn ich nur eine Spalte durchsucht habe:

query = meta.Session.query(User).filter(User.firstname.like(searchVar))
teggy
quelle
4
Ich dachte, dass diese Frage zu meinem Problem passt, aber die Antworten gelten nicht für mein spezielles Szenario. Wenn der Vorname "joe" und der Nachname "smith" ist, suche ich nach einer Filteranweisung, die übereinstimmt, wenn die angegebene searchVar "joe smith" ist. Das heißt, die Felder müssen verkettet werden (mit hinzugefügtem Speicherplatz), bevor der Test durchgeführt wird. Scheint ein sehr reales Szenario zu sein.
Groovee60
1
@ Groovee60 Genau das suche ich. Ich würde mich freuen, wenn Sie Ihre Lösung teilen könnten, wenn Sie eine gefunden hätten.
Lilylakshi

Antworten:

80

Es gibt verschiedene Möglichkeiten, dies zu tun:

Verwenden filter()( und Operator)

query = meta.Session.query(User).filter(
    User.firstname.like(search_var1),
    User.lastname.like(search_var2)
    )

Verwenden filter_by()( und Operator)

query = meta.Session.query(User).filter_by(
    firstname.like(search_var1),
    lastname.like(search_var2)
    )

Verkettung filter()oder filter_by()( und Bediener)

query = meta.Session.query(User).\
    filter_by(firstname.like(search_var1)).\
    filter_by(lastname.like(search_var2))

Unter Verwendung or_(), and_()undnot()

from sqlalchemy import and_, or_, not_

query = meta.Session.query(User).filter(
    and_(
        User.firstname.like(search_var1),
        User.lastname.like(search_var2)
    )
)
Vlad Bezden
quelle
2
Gibt es bemerkenswerte Leistungsunterschiede für diese verschiedenen Ansätze?
Miek
2
Die meisten der verschiedenen Ansätze generieren am Ende dieselbe Abfrage, sodass Sie in den meisten Fällen keinen Leistungsunterschied feststellen.
Asa Stallard
Ich bin ein bisschen verwirrt. Die filter_byDokumente sagen, dass es zum Filtern nach Schlüsselwortargumenten dient : query(Foo).filter_by(bar='baz'). Wie hängt das mit der Syntax zusammen, die Sie in Ihrer obigen Antwort verwendet haben?
Tel.
76

Sie können einfach filtermehrmals anrufen :

query = meta.Session.query(User).filter(User.firstname.like(searchVar1)). \
                                 filter(User.lastname.like(searchVar2))
David Johnstone
quelle
36
Gibt es einen Leistungsunterschied zwischen der Verwendung mehrerer filter()Methoden und der Kombination mehrerer Bedingungen (nach or_oder and_) in einer einzigen filtergroßen MySQL-Tabelle?
ExAres
6
Würden mehrere filterAnrufe ANDeher logisch als logisch sein OR?
Danodonovan
12
es wäre UND
Lyman Zerga
6
Ich würde es nicht glauben - wenn Sie sich str (User.filter (cond1) .filter (cond2)) ansehen, wird das endgültige SQL nur mit den Bedingungen "und" ed generiert.
Shankar ARUL - jupyterdata.com
60

Sie können die or_Funktion von SQLAlchemy verwenden , um in mehr als einer Spalte zu suchen (der Unterstrich ist erforderlich, um ihn von Pythons eigener zu unterscheiden or).

Hier ist ein Beispiel:

from sqlalchemy import or_
query = meta.Session.query(User).filter(or_(User.firstname.like(searchVar),
                                            User.lastname.like(searchVar)))
gclj5
quelle
7
Sie können verwenden |Operator statt or_, so - (User.firstname.like(searchVar)) | (User.lastname.like(searchVar)), aber Sie sollten vorsichtig sein |Vorrang, ohne Klammer kann es produzieren sehr unerwartete Ergebnisse , wenn sie mit comparsion Betreiber gemischt.
Daniel Kluev
1
Sollte es nicht sein filter.or_( case1, case 2)?
Fedorqui 'SO hör auf zu schaden'
2
Dies ist falsch, da es sich bei der Frage um ORM handelt, der Link jedoch zu Ausdrücken führt.
user2846569
1
Ich habe mehrere Filteranweisungen verwendet, vor denen die Latenz dramatisch erhöht wurde. Ich habe es in or_ geändert und es kehrt VIEL schneller zurück. Vielen Dank, dass Sie @ gclj5
Jimmy
1

Ein generischer Code, der für mehrere Spalten funktioniert. Dies kann auch verwendet werden, wenn Suchfunktionen in der Anwendung bedingt implementiert werden müssen.

search_key = "abc"
search_args = [col.ilike('%%%s%%' % search_key) for col in ['col1', 'col2', 'col3']]
query = Query(table).filter(or_(*search_args))
session.execute(query).fetchall()

Hinweis: Es %%ist wichtig, die% -Formatierung der Abfrage zu überspringen.

Azharullah Shariff
quelle