【问题标题】:Using jsonb_array_elements in sqlalchemy query在 sqlalchemy 查询中使用 jsonb_array_elements
【发布时间】:2019-01-22 07:00:23
【问题描述】:

我正在使用 SQLAlchemy ORM 并试图弄清楚如何生成 PostgreSQL 查询,类似于:

SELECT
    payments.*
FROM
    payments,
    jsonb_array_elements(payments.data #> '{refunds}') refunds
WHERE
    (refunds ->> 'created_at')
        BETWEEN '2018-12-01T19:30:38Z' AND '2018-12-02T19:30:38Z';

虽然包括开始日期和不包括结束日期。

我已经能够接近:

refundsInDB = db_session.query(Payment).\
    filter(Payment.data['refunds', 0, 'created_at'].astext >= startTime,
           Payment.data['refunds', 0, 'created_at'].astext < stopTime ).\
    all()

但是,这仅在退款(JSONB 数据中的嵌套数组)是{'refunds':[]} 列表中的第一个元素时才有效,而无论退款列表中的位置如何,上面的 SQL 查询都将有效。

经过一番搜索后,旧的 SQLAlchemy github issue 中似乎有一些临时食谱,其中一个谈到在查询中使用 jsonb_array_elements,但我无法完全使其适用我想要的方式。

如果它有助于我的 Payment.data JSONB 与 Payment 对象 from the Square Connect v1 API 完全一样,我正在尝试使用在 refund 对象的嵌套 refunds 列表中找到的 created_at 日期搜索数据。

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    使用Query.select_from()function expression alias 执行查询:

    # Create a column object for referencing the `value` attribute produced by
    # the set of jsonb_array_elements
    val = db.column('value', type_=JSONB)
    
    refundsInDB = db_session.query(Payment).\
        select_from(
            Payment,
            func.jsonb_array_elements(Payment.data['refunds']).alias()).\
        filter(val['created_at'].astext >= startTime,
               val['created_at'].astext < stopTime ).\
        all()
    

    请注意,取消嵌套 jsonb 数组并基于它进行过滤可能会为每个 Payment 生成多行,但 SQLAlchemy 在查询单个实体时只会返回不同的实体。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-21
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 2011-11-30
      • 2022-06-24
      相关资源
      最近更新 更多