如何让 sqlachemy 看到 json_each 或 jsonb_each 中的隐式横向连接?

Posted

技术标签:

【中文标题】如何让 sqlachemy 看到 json_each 或 jsonb_each 中的隐式横向连接?【英文标题】:How to make sqlachemy see implicit lateral joins as in json_each or jsonb_each? 【发布时间】:2021-10-29 23:11:22 【问题描述】:

我正在尝试找出使用 json_each 的正确方法。我见过一些技巧,比如使用columntext。到目前为止,我已经找到了一种使用table_valued 的非常干净的方法,除了交叉连接警告之外,它可以工作。

term = 'connection'
about_exp = func.json_each(EventHistory.event, '$.about').table_valued('value')
events = s.query(EventHistory).filter(about_exp.c.value == term)

EventHistory 包含一个 json 字段,如下所示:"about": ["antenna", "connection", "modem", "network"]

生成的查询按预期工作,但我收到以下警告: SAWarning:SELECT 语句在 FROM 元素“event_history”和 FROM 元素“anon_1”之间有一个笛卡尔积。在要解析的每个元素之间应用连接条件。

对于任何想在这里进行实验的人来说,这是一个来自单元测试的工作示例:https://gist.github.com/PiotrCzapla/579f76bdf95a485eaaafed1492d9a70e

【问题讨论】:

为什么不使用原始查询? 这是一个简化的示例,我希望能够与其他实体连接并为此使用 sqlalchemy 隐式连接。但使用文本是其中一种选择。 我认为您加入或尝试使用最新 SQL 功能的实体越多,sqlalchemy 代码就越神秘和模糊。在我看来,当您以专有的命令式方式表达声明性逻辑(并且有一个非常好的标准)时,这似乎很自然。为什么要这样做?顺便说一句,在这种特殊情况下,根本不需要连接。 select <whatever> from "EventHistory" where "event"::jsonb @> '"about":["connection"]' @> 操作真的很酷,谢谢。它在 sqlalchemy 中也得到了很好的表达。我的实际代码需要选择 json_each,因此我没有考虑替代表达式,但谢谢!随时添加此作为答案以获得投票。 【参考方案1】:

到目前为止,我发现不发出警告的唯一方法是添加join(about_exp, true())

    from sqlalchemy import true

    about_exp = func.json_each(EventHistory.event, '$.about').table_valued('value')
    events = s.query(EventHistory).join(about_exp, true()).filter(
      about_exp.c.value == about_val
    )

但它需要额外导入 true 和额外的 join 语句,如果有人有更好的解决方案,请告诉我。

【讨论】:

以上是关于如何让 sqlachemy 看到 json_each 或 jsonb_each 中的隐式横向连接?的主要内容,如果未能解决你的问题,请参考以下文章

2Python全栈之路系列之SQLAchemy

DJango - Sqlachemy - 如何生成已有数据库的models

ORM sqlachemy学习

SQLAchemy

SQLAchemy 常用操作

ORM框架/SQLAchemy