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 中的整个列强制执行唯一性约束?

SQLAlchemy JSON列包含嵌套json中的特定键

在 Flask-sqlalchemy 和 Postgresql 中使用 JSON 类型

如何级联删除一对多数据 sqlalchemy

SQLAlchemy:JSON_ARRAY_APPEND?

在SQLAlchemy中查找数组列中最常见的值