【问题标题】:SQLAlchemy join through JSON sub fieldSQLAlchemy 通过 JSON 子字段加入
【发布时间】:2020-08-30 19:25:32
【问题描述】:

我有一个现有的 SQLAlchemy 模型,它应该与另一个模型有关系,但遗憾的是,那里的连接点是 JSON PostgreSQL 列的(子)字段。

假设一个表“类别”是:

id(bigint) | name(string)
-------------------------
         5 | Comics

...第二个表“英雄”是:

id(bigint) | name(string) | info(JSON)
-------------------------------------------------------------
         2 | Tranquility  | {"category_id":5, "genre_id": 17}

我将如何在 python SQLAlchemy&PostgreSQL9.5 中通过hero 通过heroinfo["category_id"] 加入category 以获得以下结果?

id(bigint) | name(string) | category_name | info(JSON)
-------------------------------------------------------------
         2 | Tranquility  | Comics        | {"category_id":5, "genre_id": 17}

根据这个答案,我知道在 PostgreSQL 本身中这样的事情是可能的

https://dba.stackexchange.com/a/83935 (http://sqlfiddle.com/#!15/226c33/1)

并且可能需要一些技巧来转换或绕过默认方式
sqlalchemy filter by json field中所述

注意:请注意,我无法更改数据库结构或模型的现有部分,我也不是在寻找我已经知道的双重查询绕过。

【问题讨论】:

  • 在链接问题和 jsonb access+cast 模式的基础上,添加 Query.join() 接受明确的 ON 子句作为第二个参数应该让您前进。
  • @IljaEverilä 你的意思是原始 SQL 吗? (我正在寻找更多的 sql-alchemy 方式)

标签: python json postgresql join sqlalchemy


【解决方案1】:

您可以使用json_to_record 创建一个内存表,然后加入该表。

https://www.postgresql.org/docs/9.4/functions-json.html

已经回答了这个问题的另一个问题,但那是使用json_to_recordset,因为数据是对象列表 https://stackoverflow.com/a/31333794/3358570

这里是你可以根据需要转换成sqlalchemy的SQL,

SELECT hero.id as hero_id, hero.name as name, d.name as category_name, info
FROM hero,
     json_to_record(hero.info) AS x(category_id int)
         JOIN category d on d.id = category_id

这里为您提供 db fiddle https://www.db-fiddle.com/f/7ops4KXVDF6KpY5JZau7vG/1

另一种更简单的方法是在 join 中访问 JSON 值并输入 caste category_id

SELECT hero.id       AS hero_id,
       hero.name     AS hero_name,
       category.name AS category_name,
       category.id   AS category_id,
       hero.info     AS hero_info
FROM hero
     JOIN category ON category.id = CAST(hero.info ->> 'category_id' AS INTEGER)

等效的 sqalchemy 会变成,

category_id = cast(Hero.info.op("->>")("category_id"), Integer)
query = (db.session.query(Hero.id, Hero.name, Category.name, Category.id, Hero.info)
         .join(Category, Category.id == category_id))
data = query.all()

【讨论】:

  • 虽然这是一个不错的功能,但这并不能以任何方式回答我的问题,并且无论如何都不适用于我的场景。
  • 怎么样?更多细节会很有帮助
  • 我的问题是针对 python - sqlalchemy - 如何以“sqlalchemy-way”在 python 中编写这样的查询 - 我已经知道如何在 SQL 中加入 JSON - 我已经引用了 stackexchange answer & sqlfiddle 描述...我只提到了 postgre,因为它是可能导致需要更多面向方言的 sqlalchemy 库的底层引擎。总体而言我确实提供了所有细节并且在我的问题中非常彻底
  • 更新的答案,你没有明确说你需要 sqlalchemy,怎么知道你需要 SQL 或 sqlalchemy 的帮助。我的假设是您需要有关该方法的帮助。如果您只是需要将 SQL 转换为 sqlalchemy,那么您也应该发布原始 SQL。
  • 所以我终于测试了它,python/SQLAlchemy 代码确实产生了相同的查询 - 非常感谢你 :) MySQL/Percona 人的旁注 - 这是仅限 PostgreSQL 查询! (它似乎不适用于 MySQL/Percona,但它确实适用于 Postgre)
猜你喜欢
  • 2019-04-15
  • 1970-01-01
  • 1970-01-01
  • 2013-12-21
  • 1970-01-01
  • 2020-02-07
  • 2023-03-26
  • 1970-01-01
  • 2022-08-04
相关资源
最近更新 更多