【问题标题】:Flask SQLAlchemy Filter On A Postgres JSON List Object Based on a Single String基于单个字符串的 Postgres JSON 列表对象上的 Flask SQLAlchemy 过滤器
【发布时间】:2021-11-18 02:17:24
【问题描述】:

我有一个名为“测试”的模型。名为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

在我的烧瓶视图中,我抓取了一个 url 参数,我想用它来过滤测试以获取参数值在 alias json 列表中的所有测试对象。例如,如果url_param_value="a" 我想要"a"alias 中的所有测试对象。因此,["a", "b"]alias 值在此示例中会很受欢迎。

这是我的方法,但它不起作用,我认为它与序列化有关。

Testing.query.filter(Testing.alias.contains(url_param_val)).all()

我收到以下错误

NotImplementedError: Operator 'contains' is not supported on this expression

【问题讨论】:

    标签: postgresql flask sqlalchemy flask-sqlalchemy


    【解决方案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)
    

    警告:这对于大表来说效率非常低;您最好修复类型以匹配您的数据,然后创建适当的索引。

    【讨论】:

      猜你喜欢
      • 2019-12-25
      • 1970-01-01
      • 1970-01-01
      • 2021-12-27
      • 1970-01-01
      • 1970-01-01
      • 2014-08-19
      • 2022-01-14
      • 1970-01-01
      相关资源
      最近更新 更多