查询嵌套对象/表 sqlalchemy ORM

问题描述 投票:0回答:1

我的表与其他表有深层嵌套关系

@mapper_registry.mapped
@dataclass
class Project:
    __tablename__ = "project"
    __table_args__ = (#some table constraints here)

    id: float = field(init=False, metadata={"sa": Column(NUMBER(15, 0, False), primary_key=True)})
    date_created: datetime = field(metadata={"sa": Column(MyTimestamp, nullable=False)})
    user_created_id: float = field(metadata={"sa": Column(NUMBER(15, 0, False), nullable=False)})
    user_created: Optional[BiologicsUser] = field(default=None, metadata={"sa": relationship("User", foreign_keys="Project.user_created_id", backref="project")})
    
    
mapper_registry.mapped
@dataclass
class User:
    __tablename__ = "user"
    __table_args__ = ()
    __sa_dataclass_metadata_key__ = "sa"

    id: float = field(
        init=False, metadata={"sa": Column(NUMBER(15, 0, False), primary_key=True)}
    )
    name: str = field(metadata={"sa": Column(VARCHAR(100), nullable=False)})
    organization_id: Optional[float] = field(default=None, metadata={"sa": Column(NUMBER(15, 0, False))})
    department_id: Optional[float] = field(default=None, metadata={"sa": Column(NUMBER(15, 0, False))})
    site_id: Optional[float] = field(default=None, metadata={"sa": Column(NUMBER(15, 0, False))})
    department: Optional[Department] = field(default=None,metadata={"sa": relationship("Department", backref="user")})
    organization: Optional[Organization] = field(default=None,metadata={"sa": relationship("Organization", backref="user")})
    site: Optional[Site] = field(default=None,metadata={"sa": relationship("Organization", backref="user")})
    
    

@dataclass
class Department:
    __tablename__ = "department"
    __table_args__ = ( )
    __sa_dataclass_metadata_key__ = "sa"

    id: float = field(init=False, metadata={"sa": Column(NUMBER(15, 0, False), primary_key=True)})
    label: str = field(metadata={"sa": Column(VARCHAR(255), nullable=False)})

@dataclass
class Organization:
    __tablename__ = "organization"
    __table_args__ = ( )
    __sa_dataclass_metadata_key__ = "sa"

    id: float = field(init=False, metadata={"sa": Column(NUMBER(15, 0, False), primary_key=True)})
    label: str = field(metadata={"sa": Column(VARCHAR(255), nullable=False)})
    
@dataclass
class Site:
    __tablename__ = "site"
    __table_args__ = ( )
    __sa_dataclass_metadata_key__ = "sa"

    id: float = field(init=False, metadata={"sa": Column(NUMBER(15, 0, False), primary_key=True)})
    label: str = field(metadata={"sa": Column(VARCHAR(255), nullable=False)})

当我使用

查询项目时
session.execute(select(Project)).all()

我为项目中的所有列获取了一个嵌套字典/对象,并按预期嵌套了 user_created 列。但我不需要返回所有这些,因为它是一棵嵌套对象的大树。所以我尝试指定所需的字段

当我尝试选择 id 和 user_created

select(Project.id, Project.user_created)
例如,我收到错误

ORA-00923: FROM keyword not found where expected
E   Help: https://docs.oracle.com/error-help/db/ora-00923/
E   [SQL: SELECT project.id, user.id = project.user_created_id AS anon_1
E   FROM project, user]  - sqlalchemy.exc.DatabaseError: (oracledb.exceptions.DatabaseError) ORA-00923: FROM keyword not found where expected

我天真的想法是,既然我可以获得包括嵌套列在内的所有列,我应该能够只选择我需要的列并加载所有嵌套列。所以我尝试了

query = select(Project).options(load_only(Project.id, Project.user_created))

出现错误

Can't apply "column loader" strategy to property "Project.user_created", which is a "relationship"; this loader strategy is intended to be used with a "column property".

所以我改变了

query = select(Project).options(load_only(project.id), selectinload(Project.user_created))

还是失败了。不太确定我做错了什么。

python oracle sqlalchemy orm fastapi
1个回答
0
投票

这有点令人困惑,但我认为关键问题是列和关系之间的模糊区别。像

project.id
是一列,而
project.user_created
是一种关系,即。另一个模型。你必须以不同的方式对待这些。您可以通过在引擎上设置
echo=True
来检查会发生什么情况。

这里有几个例子:

A.使用 pure-orm,您可以将项目对象限制为仅包含
id
列,然后使用另一个查询加载
user_created
关系。
q = select(Project).options(load_only(Project.id), selectinload(Project.user_created))
for project in session.scalars(q):
    print (project.id, project.user_created.id)
B.选择
id
列和
user_created
对象,但您必须自己指定联接,这应该使用单个查询。
q = select(Project.id, Project.user_created).join(Project.user_created)
for project_id, project_user_created in session.execute(q):
    print (project.id, project.user_created.id)

© www.soinside.com 2019 - 2024. All rights reserved.