如何查询 JSON 元素

How to query a JSON element

假设我有一个 Postgres 数据库 (9.3) 并且有一个名为 Resources 的 table。在 Resources table 我有字段 id 是一个 int 和 data 这是一个 JSON 类型。

假设我在 table.

中有以下记录

我想要做的是编写一个查询,该查询将 return 数据列中具有 json 元素且姓氏等于 "Doe"[=16] 的所有记录=]

我试过这样写:

records = db_session.query(Resource).filter(Resources.data->>'lastname' == "Doe").all()

Pycharm 但是在“->>”

上给我一个编译错误

有谁知道我将如何编写过滤器子句来完成我需要的事情?

尝试使用 astext

records = db_session.query(Resource).filter(
              Resources.data["lastname"].astext == "Doe"
          ).all()

请注意,该列的类型必须为 JSONB。常规 JSON 列将不起作用。

您也可以将字符串显式转换为 JSON(请参阅 Postgres JSON type doc)。

from sqlalchemy.dialects.postgres import JSON
from sqlalchemy.sql.expression import cast
db_session.query(Resource).filter(
    Resources.data["lastname"] == cast("Doe", JSON)
).all()

根据sqlalchemy.types.JSON,你可以这样做

from sqlalchemy import JSON
from sqlalchemy import cast
records = db_session.query(Resource).filter(Resources.data["lastname"] == cast("Doe", JSON)).all()

如果您使用的是 JSON 类型(而不是 JSONB),以下对我有用:

注意 '"object"'

    query = db.session.query(ProductSchema).filter(
        cast(ProductSchema.ProductJSON["type"], db.String) != '"object"'
    )

我在 JSON(不是 JSONB)类型的列中有一些 GeoJSON,现有解决方案中的 none 有效,但事实证明,在版本 1.3.11 中添加了一些新的数据转换器,所以现在您可以:

records = db_session.query(Resource).filter(Resources.data["lastname"].as_string() == "Doe").all()

参考:https://docs.sqlalchemy.org/en/14/core/type_basics.html#sqlalchemy.types.JSON

Casting JSON Elements to Other Types

Index operations, i.e. those invoked by calling upon the expression using the Python bracket operator as in some_column['some key'], return an expression object whose type defaults to JSON by default, so that further JSON-oriented instructions may be called upon the result type. However, it is likely more common that an index operation is expected to return a specific scalar element, such as a string or integer. In order to provide access to these elements in a backend-agnostic way, a series of data casters are provided:

Comparator.as_string() - return the element as a string

Comparator.as_boolean() - return the element as a boolean

Comparator.as_float() - return the element as a float

Comparator.as_integer() - return the element as an integer

These data casters are implemented by supporting dialects in order to assure that comparisons to the above types will work as expected, such as:

# integer comparison
data_table.c.data["some_integer_key"].as_integer() == 5

# boolean comparison
data_table.c.data["some_boolean"].as_boolean() == True

根据this,1.3.11 之前的版本,最稳健的方法应该是这样的,因为它适用于多种数据库类型,例如SQLite,MySQL,Postgres:

from sqlalchemy import cast, JSON, type_coerce, String

db_session.query(Resource).filter(
    cast(Resources.data["lastname"], String) == type_coerce("Doe", JSON)
).all()

从 1.3.11 版本开始,特定类型的脚轮是处理这个问题的新的更简洁的方法:

db_session.query(Resource).filter(
    Resources.data["lastname"].as_string() == "Doe"
).all()