SQLAlchemy equivale all'istruzione SQL "LIKE"


87

Una colonna di tag ha valori come "mela banana arancia" e "fragola banana limone". Voglio trovare l'istruzione equivalente a SQLAlchemy

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

A cosa devo passare Class.query.filter()per farlo?

Risposte:


177

Ogni colonna ha un like()metodo, che può essere utilizzato in query.filter(). Data una stringa di ricerca, aggiungi un %carattere su entrambi i lati per cercare come sottostringa in entrambe le direzioni.

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

1
Perfetto! Sai se c'è un modo migliore per distinguere tra mela e ananas rispetto all'aggiunta di uno spazio principale?
Gary Oldfaber

3
Il modo migliore sarebbe normalizzare il database e aggiungere 2 tabelle separate per i tag e le relazioni tra tag e attività, quindi utilizzare JOIN invece di LIKE. Altrimenti, sì, sembra che dovrai avere una sorta di separatore attorno a ciascun tag nella stringa. Lo spazio iniziale non è sufficiente, poiché ci sono anche penna e matita, con% pen%. Se fai qualcosa come "| mela | ananas | penna | matita |" e corrisponde a "% | pen |%" non dovrebbe entrare in collisione.
Daniel Kluev

1
Con la normalizzazione, non sono abbastanza sicuro di come avrò più di un tag associato a una determinata attività o viceversa utilizzando la mappa dei tag. La soluzione "Toxi" sembra raggruppare la raccolta di tag come un unico elemento, piuttosto che archiviarli singolarmente? E il metodo utilizzato in questa ricetta ( elixir.ematia.de/trac/wiki/Recipes/TagCloud ) sembra consentire solo un tag per articolo. Quali risorse sarebbero migliori per chiarire questo argomento? Ho letto anche questo ( dev.mysql.com/tech-resources/articles/… ), ma non riesco a immaginare come gestire più tag.
Gary Oldfaber

2
Come ho detto, hai bisogno di due tavoli. Fondamentalmente, è solo la tipica relazione Molti-a-Molti, quindi puoi seguire la guida di SQLAlchemy su di essa: sqlalchemy.org/docs/… Avrai una tagstabella, dove memorizzi il nome del tag e altre informazioni sui tag, e avrai una task_tagstabella, che avrà un record per ogni tag aggiunto all'attività. Quindi l'attività con 2 tag avrà solo 2 record nella task_tagstabella.
Daniel Kluev

12

Aggiungendo alla risposta sopra, chiunque cerchi una soluzione, puoi anche provare l'operatore "match" invece di "like". Non voglio essere di parte, ma ha funzionato perfettamente per me in Postgresql.

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

Eredita le funzioni del database come CONTAINS e MATCH . Tuttavia, non è disponibile in SQLite.

Per maggiori informazioni vai su Common Filter Operators


8
Qual è la differenza tra questi due operatori?
buhtz

@buhtz dipende dal tuo backend DB vedi documentazione SQL-Alchemy: docs.sqlalchemy.org/en/14/core/… In Postgres ottieni to_tsqueryche ti consente di aggiungere operatori di testo per cose come ORe AND postgresql.org/docs/current/…
Nick

8

prova questo codice

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


0

Se usi sql nativo, puoi fare riferimento al mio codice, altrimenti ignora la mia risposta.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.