【问题标题】:SQLAlchemy: filtering on values stored in nested list of the JSONB fieldSQLAlchemy:过滤存储在 JSONB 字段的嵌套列表中的值
【发布时间】:2017-01-20 11:39:42
【问题描述】:

假设我有一个名为 Item 的模型,其中包含一个 JSONB 字段 data。其中一条记录存储了以下 JSON 对象:

{
    "name": "hello",
    "nested_object": {
        "nested_name": "nested"
    },
    "nested_list": [
        {
            "nested_key": "one"
        },
        {
            "nested_key": "two"
        }
    ]
}

我可以通过过滤name 字段找到这条记录:

Session().query(Item).filter(Item.data["name"] == "hello")

我可以通过过滤嵌套对象来找到这条记录:

Session().query(Item).filter(Item.data[("nested_object","nested_name")] == "hello")

但是,我正在努力寻找一种方法来通过过滤存储在嵌套列表中的项目的值来找到此记录。 换句话说,如果用户提供了值“一”,我想找到上面的记录,并且我知道在 nested_list 内的键 nested_key 中查找它。

是否可以使用可用的 SQLAlchemy 过滤器来实现这一点?

【问题讨论】:

    标签: python json postgresql sqlalchemy


    【解决方案1】:

    SQLAlchemy 的 JSONB 类型具有 contains() 方法,用于 Postgresql 中的 @> 运算符。 The @> operator 用于检查左侧值是否包含顶层的正确 JSON 路径/值条目。你的情况

    data @> '{"nested_list": [{"nested_key": "one"}]}'::jsonb
    

    或者在python中

    the_value = 'one'
    
    Session().query(Item).filter(Item.data.contains(
        {'nested_list': [{'nested_key': the_value}]}
    ))
    

    该方法将您的 python 结构转换为适合数据库的 JSON 字符串。

    在 Postgresql 12 中,您可以使用 JSON path 函数:

    import json
    
    Session().query(Item).\
        filter(func.jsonb_path_exists(
            Item.data,
            '$.nested_list[*].nested_key ? (@ == $val)',
            json.dumps({"val": the_value})))
    

    【讨论】:

    • 感谢您的回复。我在将字典传递给“包含”函数时收到一条错误消息:“psycopg2.ProgrammingError:无法适应类型'dict'”。我尝试让 contains 函数与其他语法变体一起使用,但无济于事。
    • 你的 SQLAlchemy 版本是多少?
    • 另外,您是否尝试过 Item.data[("nested_object","nested_name")].contains(...) 或类似的而不是 Item.data.contains(...)?对JSONB 列的项目访问返回一个JSONElement 对象,该对象缺少比较器方法。您还应该在问题中包含模型类定义,以确保我们在同一页面上。
    猜你喜欢
    • 2015-03-28
    • 2021-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-31
    • 2023-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多