我正在使用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就像付款对象from the Square Connect v1 API一样,我正尝试使用{的嵌套created_at
列表中的refunds
日期来搜索数据{1}}个对象。
答案 0 :(得分: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在查询单个实体时只会返回不同的实体。