SQL "LIKE" ifadesine eşdeğer SQLAlchemy


87

Bir etiket sütunu, "elma muzlu portakal" ve "çilekli muz limon" gibi değerlere sahiptir. SQLAlchemy eşdeğer ifadesini bulmak istiyorum

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

Bunu Class.query.filter()yapmak için neye geçmeliyim ?

Yanıtlar:


177

Her sütunun içinde kullanılabilecek bir like()yöntemi vardır query.filter(). Bir arama dizesi verildiğinde %, her iki yönde bir alt dize olarak aramak için her iki tarafa da bir karakter ekleyin .

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

1
Mükemmel! Elma ile ananası birbirinden ayırmanın, boşluk eklemekten daha iyi bir yolu olup olmadığını biliyor musunuz?
Gary Oldfaber

3
En iyi yol, veritabanınızı normalleştirmek ve etiketler ve etiket-görev ilişkileri için 2 ayrı tablo eklemek ve ardından LIKE yerine JOIN kullanmaktır. Aksi takdirde, evet, dizedeki her etiketin etrafında bir tür ayırıcıya sahip olmanız gerekecek gibi görünüyor. Ayrıca% pen% ile kalem ve kurşun kalem de olduğu için lider alan yeterli değildir. "| Elma | ananas | kalem | kurşun kalem |" gibi bir şey yaparsanız ve "% | pen |%" ile eşleşir, çakışmamalıdır.
Daniel Kluev

1
Normalleştirmeyle, belirli bir görevle ilişkili birden fazla etiketin nasıl olacağından emin değilim veya tam tersi, etiket haritasını kullanarak. "Toxi" çözümü, etiket koleksiyonunu her birini ayrı ayrı depolamak yerine tek bir öğe olarak gruplandırıyor gibi görünüyor. Ve bu tarifte ( elixir.ematia.de/trac/wiki/Recipes/TagCloud ) kullanılan yöntem, her öğe için yalnızca bir etikete izin veriyor gibi görünüyor. Bu konuyu aydınlatmak için en iyi kaynaklar hangileridir? Bunu da okudum ( dev.mysql.com/tech-resources/articles/… ), ancak birden fazla etiketin nasıl yönetileceğini hayal edemiyorum.
Gary Oldfaber

2
Dediğim gibi, iki masaya ihtiyacınız var. Temel olarak, onun sadece tipik Birçok-çok ilişkisi, üzerinde sqlalchemy kılavuzuna takip edebilirsiniz: sqlalchemy.org/docs/... Olacak tagsetiket adını ve diğer etiket bilgileri depolamak tablo, ve sahip olacak task_tags, tablo hangi göreve eklenen her etiket için bir kayıt olacaktır. Yani 2 etiketli görevin task_tagstabloda sadece 2 kaydı olacaktır .
Daniel Kluev

12

Yukarıdaki cevaba ek olarak, kim bir çözüm ararsa, "beğen" yerine "eşleştir" operatörü de deneyebilirsiniz. Önyargılı olmak istemiyorum ama Postgresql'de benim için mükemmel çalıştı.

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

CONTAINS ve MATCH gibi veritabanı işlevlerini devralır . Ancak, SQLite'de mevcut değildir.

Daha fazla bilgi için Ortak Filtre Operatörlerine gidin


8
Bu iki operatör arasındaki fark nedir?
buhtz

@buhtz, DB arka ucunuza bağlıdır, bkz. SQL-Alchemy docs: docs.sqlalchemy.org/en/14/core/… Postgres'te, ve postgresql.org/docs/current/…to_tsquery gibi şeyler için metin operatörleri eklemenize izin verirsinizORAND
Nick

8

bu kodu dene

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

1

PostgreSQL kullanarak like( yukarıda kabul cevaba bakınız benim için bir türlü iş vermedi) vakalar eşleşti rağmen , ancak ilike(vaka i nsensisitive gibi ) yapar.


2
ILIKEöğesinin büyük / küçük harfe duyarlı olmayan sürümü LIKEolduğundan, girdileriniz yalnızca duruma göre farklılık gösterir.
Martijn Pieters

0

Yerel sql kullanıyorsanız, koduma başvurabilirsiniz, aksi takdirde cevabımı göz ardı edebilirsiniz.

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.