我是 SQLAlchemy 的第一次用户,它与 PostgreSQL、FastAPI 和数据库库一起使用。我无法将工作的原始查询转换为 SQLAlchemy 方法,特别是在将列类型确定为jsonb[]
并将其包含在json_agg
函数中时。我正在使用sqlalchemy_utils
类型转换JSON
和JSONB
to SQL
。
我试图复制的原始查询。
SELECT pr.id, pr.name, json_agg(f) as features FROM projects pr
LEFT JOIN features f ON f.project_id = pr.id
WHERE pr.id IN ('1')
GROUP BY(pr.id);
我通过使用上面我试图在 SQLAlchemy 中复制的查询得到的目标响应
[
{
"id": "c7b0af60-3db4-4f07-a397-ee5d8123c88e",
"name": "Test Name",
"features": [
{
"id": "b5c441f8-79b8-452b-9a42-6c7fc976ca2b",
"name": "Another Test Name",
"created_at": "2021-02-01T20:51:26.998+00:00",
"finished_at": "2021-02-17T20:51:26+00:00",
"project_id": "c7b0af60-3db4-4f07-a397-ee5d8123c88e",
"items": null
},
{
"id": "4f03a7f0-eb32-4aae-84aa-678984b46132",
"name": "Yet Another Test Name",
"created_at": "2021-02-01T20:51:26.998+00:00",
"finished_at": "2021-02-20T20:51:26+00:00",
"project_id": "c7b0af60-3db4-4f07-a397-ee5d8123c88e",
"items": null
},
{
"id": "7a81da18-409a-4d1d-85cc-308b5c58b5e8",
"name": "Test Name",
"created_at": "2021-02-01T18:27:42.146+00:00",
"finished_at": "2021-03-05T18:27:42+00:00",
"project_id": "c7b0af60-3db4-4f07-a397-ee5d8123c88e",
"items": [
{
"id": "8672001a-833c-4600-bc3b-025ed6451f05",
"name": "Test Name",
"type": "Test Type",
"s3_link": null
}
]
}
]
}
]
下面是我的表以及我如何使用 SQLAlchemy 定义它们。
from sqlalchemy import Table, Column, String, ForeignKey
from sqlalchemy.dialects.postgresql import UUID, ARRAY, TIMESTAMP, JSONB
from db.db import metadata
features = Table('features', metadata,
Column('id', UUID, primary_key=True),
Column('project_id', UUID, ForeignKey('projects.id')),
Column('name', String(255)),
Column('created_at', TIMESTAMP),
Column('finished_at', TIMESTAMP),
Column('items', ARRAY(JSONB))
)
projects = Table('projects', metadata,
Column("id", UUID, primary_key=True),
Column("name", String(255))
)
如果我items
从feature_obj
.
from schema.projects_table import projects
from schema.features_table import features
from sqlalchemy import select, func
from sqlalchemy_utils import json_sql, jsonb_sql,
async def select_from_list(project_ids: List[UUID]):
feature_obj = json_sql({
'id': features.c.id,
'name': features.c.name,
'project_id': features.c.project_id,
'created_at': features.c.created_at,
'finished_at': features.c.finished_at,
'items': jsonb_sql(features.c.items) # Works if I remove but doesn't include items list of jsonb
})
sel_st = select([projects.c.id, projects.c.name, func.json_agg(feature_obj).label('features')]) \
.select_from(projects.join(features, features.c.project_id == projects.c.id))\
.where(projects.c.id.in_(project_ids)) \
.group_by(projects.c.id)
rows = await db.fetch_all(sel_st)
return rows
这会产生此查询,其中items
列似乎没有转换为实际列
SELECT projects.id, projects.name, json_agg(json_build_object('id', features.id, 'name', features.name, 'project_id', features.project_id, 'created_at', features.created_at, 'finished_at', features.finished_at, 'items', :json_build_object_1)) AS features
FROM projects JOIN features ON features.project_id = projects.id
WHERE projects.id IN (:id_1, :id_2, :id_3, :id_4)
GROUP BY projects.id
我得到这个回溯说它无法确定应该是的列类型jsonb[]
statement = await self._protocol.prepare(stmt_name, query, timeout)
File "asyncpg/protocol/protocol.pyx", line 163, in prepare
asyncpg.exceptions.IndeterminateDatatypeError: could not determine data type of parameter $2
任何帮助或指示将不胜感激,因为我已经坚持了几天了。