SQLAlchemy JSON 列 - 如何执行包含查询
Posted
技术标签:
【中文标题】SQLAlchemy JSON 列 - 如何执行包含查询【英文标题】:SQLAlchemy JSON column - how to perform a contains query 【发布时间】:2017-01-21 01:37:07 【问题描述】:我在mysql(5.7.12)中有下表:
class Story(db.Model):
sections_ids = Column(JSON, nullable=False, default=[])
sections_ids 基本上是一个整数列表 [1, 2, ...,n]。 我需要获取sections_ids包含X的所有行。 我尝试了以下方法:
stories = session.query(Story).filter(
X in Story.sections_ids
).all()
但它会抛出:
NotImplementedError: Operator 'contains' is not supported on this expression
【问题讨论】:
【参考方案1】:使用JSON_CONTAINS(json_doc, val[, path])
:
from sqlalchemy import func
# JSON_CONTAINS returns 0 or 1, not found or found. Not sure if MySQL
# likes integer values in WHERE, added == 1 just to be safe
session.query(Story).filter(func.json_contains(Story.section_ids, X) == 1).all()
当您在顶层搜索数组时,您不需要提供路径。或者,从 8.0.17 开始,您可以使用 value MEMBER OF(json_array)
,但在我看来,在 SQLAlchemy 中使用它不太符合人体工程学:
from sqlalchemy import literal
# self_group forces generation of parenthesis that the syntax requires
session.query(Story).filter(literal(X).bool_op('MEMBER OF')(Story.section_ids.self_group())).all()
【讨论】:
您可以阅读 SQLA here 中的泛型函数。 你确定那是正确的语法吗?它对我不起作用...没有引发错误...只是没有继续下一行... 应该是 str(X)... (在我的情况下 X 是 int 并且只有在转换为字符串时才有效)。谢谢! 我要进行二级搜索,如何指定路径? 是 MySQL 不允许在带有JSON_CONTAINS
的 json 路径中使用通配符。相反,您可以搜索具有所需键值对的对象:func.json_contains(Foo.bar, func.json_object("some_field", "some_value"))
。【参考方案2】:
对于到达这里但正在使用 PostgreSQL 的人:
您的字段应该是 sqlalchemy.dialects.postgresql.JSONB
类型(而不是 sqlalchemy_utils.JSONType)-
然后您可以使用与字段关联的Comparator
对象及其contains
(和其他)运算符。
例子:
Query(Mymodel).filter(MyModel.managers.comparator.contains(["user@gmail.com"]))
(注意,包含的部分必须是JSON片段,而不仅仅是字符串)
【讨论】:
MyModel.managers
在这种情况下是列名(“managers”),而不是一些特殊的关键字。以上是关于SQLAlchemy JSON 列 - 如何执行包含查询的主要内容,如果未能解决你的问题,请参考以下文章
如何对 SQLAlchemy 中的整个列强制执行唯一性约束?