#postgresql #flask #sqlalchemy #flask-sqlalchemy
Вопрос:
У меня есть модель под названием Тестирование. Вызываемое поле alias
является полем JSON (на самом деле списком) и имеет такие значения, как ["a", "b"]
или ["d", "e"]
и так далее.
class Testing(db.Model):
__tablename__ = 'testing'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(25))
alias = db.Column(JSON)
def __init__(self, name, alias):
self.name = name
self.alias = alias
В моем представлении flask я выбираю параметр url, который я хочу использовать для фильтрации тестирования, чтобы получить все объекты тестирования, в которых значение параметра находится в списке alias
json. Так, например, если url_param_value="a"
я хочу, чтобы все объекты тестирования находились там, где "a"
есть alias
. Таким alias
образом, значение ["a", "b"]
будет хитом в этом примере.
Вот мой подход, но он не работает, и я предполагаю, что это связано с сериализацией.
Testing.query.filter(Testing.alias.contains(url_param_val)).all()
Я получаю следующую ошибку
NotImplementedError: Operator 'contains' is not supported on this expression
Ответ №1:
name
Поле является типом JSON, а не типом массива. У столбцов JSON нет contains
метода, даже если вы храните данные массива (как об этом узнает база данных?)
В Postgres вы можете использовать json_array_elements
для расширения массива JSON до набора значений JSON; это вернет по одной строке на элемент:
select id, json_array_elements(alias) as val from testing;
id | val
--------- --------------------
1 | "a"
2 | "b"
Вы можете использовать это в качестве подзапроса для выбора записей, содержащих соответствующее значение:
select t.id, t.name, t.alias, cast(q.val as varchar)
from testing t, (
select id, json_array_elements(alias) as val
from testing
) q
where q.id=t.id and cast(q.val as varchar) = '"a"';
В синтаксисе SQLAlchemy:
subq = session.query(
Testing.id,
func.json_array_elements(Testing.alias).label("val")
).subquery()
q = session.query(Testing).filter(
cast(subq.c.val, sa.Unicode) == '"a"',
subq.c.id == Testing.id)
Предупреждение: это будет очень неэффективно для больших таблиц; вам, вероятно, лучше исправить типы, соответствующие вашим данным, а затем создать соответствующие индексы.