SQLAlchemy entspricht der SQL-Anweisung "LIKE"


84

Eine Tags-Spalte enthält Werte wie "Apfel-Bananen-Orange" und "Erdbeer-Bananen-Zitrone". Ich möchte die entsprechende SQLAlchemy-Anweisung finden

SELECT * FROM table WHERE tags LIKE "%banana%";

Was soll ich Class.query.filter()tun, um dies zu tun?

Antworten:


170

Jede Spalte verfügt über eine like()Methode, die in verwendet werden kann query.filter(). Fügen Sie bei gegebener Suchzeichenfolge %auf beiden Seiten ein Zeichen hinzu, um als Teilzeichenfolge in beide Richtungen zu suchen.

tag = request.form["tag"]
search = "%{}%".format(tag)
posts = Post.query.filter(Post.tags.like(search)).all()

1
Perfekt! Wissen Sie, ob es einen besseren Weg gibt, zwischen Apfel und Ananas zu unterscheiden, als ein führendes Leerzeichen hinzuzufügen?
Gary Oldfaber

3
Am besten normalisieren Sie einfach Ihre Datenbank, fügen zwei separate Tabellen für Tags und Tag-zu-Task-Beziehungen hinzu und verwenden dann JOINs anstelle von LIKE. Andernfalls scheint es so, als müssten Sie um jedes Tag in der Zeichenfolge eine Art Trennzeichen setzen. Der führende Platz reicht nicht aus, da es auch Stift und Bleistift mit% pen% gibt. Wenn Sie etwas wie "| Apfel | Ananas | Stift | Bleistift |" tun und mit "% | pen |%" übereinstimmen, sollte es nicht kollidieren.
Daniel Kluev

1
Beim Normalisieren bin ich mir nicht ganz sicher, wie ich einer bestimmten Aufgabe mehr als ein Tag zuordnen kann oder umgekehrt, wenn ich die Tag-Map verwende. Die "Toxi" -Lösung scheint die Sammlung von Tags als ein einzelnes Element zu gruppieren, anstatt jedes einzeln zu speichern. Und die in diesem Rezept verwendete Methode ( elixir.ematia.de/trac/wiki/Recipes/TagCloud ) scheint nur ein Tag pro Element zuzulassen. Welche Ressourcen eignen sich am besten zur Erläuterung dieses Themas? Ich habe dies auch gelesen ( dev.mysql.com/tech-resources/articles/… ), kann mir aber nicht vorstellen , wie mehrere Tags verwaltet werden sollen.
Gary Oldfaber

2
Wie gesagt, du brauchst zwei Tische. Grundsätzlich ist es nur eine typische Viele-zu-Viele-Beziehung, daher können Sie dem SQLAlchemy-Handbuch folgen: sqlalchemy.org/docs/… Sie haben eine tagsTabelle, in der Sie den Tag-Namen und andere Tag-Informationen speichern, und Sie haben eine task_tagsTabelle, die Für jedes der Aufgabe hinzugefügte Tag wird ein Datensatz hinzugefügt. Eine Aufgabe mit 2 Tags enthält also nur 2 Datensätze in der task_tagsTabelle.
Daniel Kluev

11

Wenn Sie zu der obigen Antwort hinzufügen, wer auch immer nach einer Lösung sucht, können Sie auch den Operator "Übereinstimmung" anstelle von "Gefällt mir" versuchen. Ich möchte nicht voreingenommen sein, aber es hat perfekt für mich in Postgresql funktioniert.

Note.query.filter(Note.message.match("%somestr%")).all()

Es erbt Datenbankfunktionen wie CONTAINS und MATCH . Es ist jedoch in SQLite nicht verfügbar.

Weitere Informationen finden Sie unter Allgemeine Filteroperatoren


8
Was ist der Unterschied zwischen diesen beiden Operatoren?
Buhtz

@buhtz hängt von Ihrem DB-Backend ab. Siehe SQL-Alchemy-Dokumente: docs.sqlalchemy.org/en/14/core/… In Postgres erhalten Sie Textoperatorento_tsquery für Dinge wie ORund AND postgresql.org/docs/current/…
Nick vor

7

Versuchen Sie diesen Code

output = dbsession.query(<model_class>).filter(<model_calss>.email.ilike('%' + < email > + '%'))

1

Die Verwendung von PostgreSQL like( siehe akzeptierte Antwort oben ) hat bei mir irgendwie nicht funktioniert, obwohl die Fälle übereinstimmten , aber ilike(wenn ich nicht empfindlich bin wie ).


2
ILIKEist die Version von LIKE, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird , sodass sich Ihre Eingaben nur für den Fall unterschieden.
Martijn Pieters

0

Wenn Sie natives SQL verwenden, können Sie auf meinen Code verweisen, andernfalls ignorieren Sie einfach meine Antwort.

SELECT * FROM table WHERE tags LIKE "%banana%";
from sqlalchemy import text

bar_tags = "banana"

# '%' attention to spaces
query_sql = """SELECT * FROM table WHERE tags LIKE '%' :bar_tags '%'"""

# db is sqlalchemy session object
tags_res_list = db.execute(text(query_sql), {"bar_tags": bar_tags}).fetchall()

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.