【问题标题】:How to make sqlachemy see implicit lateral joins as in json_each or jsonb_each?如何让 sqlachemy 看到 json_each 或 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,因此我没有考虑替代表达式,但谢谢!随时添加此作为答案以获得投票。

标签: json postgresql sqlalchemy


【解决方案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 语句,如果有人有更好的解决方案,请告诉我。

【讨论】:

    猜你喜欢
    • 2019-12-30
    • 2014-09-25
    • 1970-01-01
    • 1970-01-01
    • 2016-06-21
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多