SQLAlchemy. Содержит нечувствительный к регистру and_ query - PullRequest
0 голосов
/ 18 февраля 2020

Я сейчас пытаюсь заставить запрос работать без учета регистра. В настоящее время запрос работает с учетом регистра, например:

and_(db.data.contains({'collections': [{'idType': id_type, 'InternalId': internal_id}]}))

Цель этого - создать N количество поисковых фильтров для запроса к базе данных. Это проверка определенной коллекции, содержащей данные, предоставленные функции. Когда я пробовал ilike или func.lower внутри контейнера, он выдает ошибку keys must be str, int, float, bool or None, not Function sqlalchemy или подобное. Также, похоже, нет функции .icontains, и все подобные вопросы .filter stackoverflow не соответствуют моей проблеме.

Мой вопрос: может ли .contains проверить значения в БД независимо от регистра? , так что запрос для

{'collections': [{'idType': 'Foo', 'InternalId': 'Bar'}]}

вернет любые значения БД с collection.idType из (Foo, FOO, foo, et c) и collection.externalId из (Bar, BAR, bar, et c)

1 Ответ

0 голосов
/ 18 февраля 2020

Решение состоит в том, чтобы удалить массив с помощью json(b)_array_elements, а затем использовать выражение подзапроса EXISTS. Для модели

class Foo(Base):
    __tablename__ = 'foo'
    id = Column(Integer, primary_key=True)
    data = Column(JSONB)

и

session.add(Foo(data={'collections': [{'idType': 'Foo', 'InternalId': 'Bar'}]}))
session.commit()

Запрос будет

from sqlalchemy import column, exists, func

cs = func.jsonb_array_elements(Foo.data["collections"]).alias("cs")
id_type = column("cs", type_=JSONB)["idType"].astext
internal_id = column("cs", type_=JSONB)["InternalId"].astext

session.query(Foo).\
    filter(exists().select_from(cs).where(and_(
        func.lower(id_type) == "foo",
        func.lower(internal_id) == "bar"))).\
    all()

То же самое в необработанном SQL немного проще для глаз в этом случае:

SELECT *
FROM foo
WHERE EXISTS (
    SELECT *
    FROM jsonb_array_elements(foo.data -> 'collections') cs
    WHERE lower(cs ->> 'idType') = 'foo'
      AND lower(cs ->> 'InternalId') = 'bar'
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...