SQLAlchemy еквівалентно оператору SQL “LIKE”


85

У стовпці тегів є такі значення, як "яблучний банан апельсин" і "полуничний банан лимон". Я хочу знайти еквівалент оператора SQLAlchemy

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

На що мені перейти, Class.query.filter()щоб зробити це?

Відповіді:


173

Кожен стовпець має like()метод, який можна використовувати в query.filter(). Враховуючи рядок пошуку, додайте %символ по обидва боки, щоб шукати як підрядок в обох напрямках.

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

1
Ідеально! Чи знаєте ви, чи є кращий спосіб відрізнити яблуко від ананаса, ніж додати провідний пробіл?
Gary Oldfaber

3
Найкращим способом було б просто нормалізувати свою базу даних і додати 2 окремі таблиці для тегів та відносин між тегами і завданнями, а потім використовувати JOIN замість LIKE. Інакше так, здається, вам доведеться мати якийсь розділювач навколо кожного тегу в рядку. Провідного місця недостатньо, оскільки є також ручка та олівець із% pen%. Якщо ви робите щось на зразок "| яблуко | ананас | ручка | олівець |" і відповідати "% | pen |%" він не повинен стикатися.
Daniel Kluev

1
При нормалізації я не зовсім впевнений, як у мене буде пов’язано більше одного тегу з даним завданням, або навпаки, використовуючи карту тегів. Рішення "Toxi", здається, групує колекцію тегів як один елемент, а не зберігає кожен окремо? І метод, використаний у цьому ( elixir.ematia.de/trac/wiki/Recipes/TagCloud ) рецепті, схоже, дозволяє лише один тег на елемент. Які ресурси були б найкращими для з’ясування цієї теми? Я також читав це ( dev.mysql.com/tech-resources/articles/… ), але не можу уявити, як керувати кількома тегами.
Gary Oldfaber

2
Як я вже сказав, вам потрібні дві таблиці. По суті, це просто типове відношення "Багато до багатьох", тому ви можете слідувати на ньому керівництву SQLAlchemy: sqlalchemy.org/docs/ ... У вас буде tagsтаблиця, де ви зберігаєте ім'я тегу та іншу інформацію про теги, і у вас буде task_tagsтаблиця, яка матиме один запис для кожного тегу, доданого до завдання. Отже, завдання з 2 тегами матиме лише 2 записи в task_tagsтаблиці.
Daniel Kluev

11

Додавши до наведеної вище відповіді, той, хто шукає рішення, також може спробувати оператор "match" замість "like". Не хочу бути упередженим, але це прекрасно спрацювало для мене в Postgresql.

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

Він успадковує такі функції бази даних, як CONTAINS та MATCH . Однак він недоступний у SQLite.

Для отримання додаткової інформації перейдіть до Загальних операторів фільтрів


8
У чому різниця між цими двома операторами?
buhtz

@buhtz залежить від ваших БД серверними см документації SQL-Alchemy: docs.sqlalchemy.org/en/14/core / ... У Postgres ви отримуєте , to_tsqueryякий дозволяє додавати текстові оператори для таких речей , як ORі AND postgresql.org/docs/current / ...
Нік

7

спробуйте цей код

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


0

Якщо ви використовуєте рідний sql, ви можете звернутися до мого коду, інакше просто проігноруйте мою відповідь.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.