1

我有一个用关系定义的表,我注意到即使我没有在查询中使用联接,仍然会检索到信息:

class Employee(Base):
    __tablename__ = "t_employee"

    id = Column(Identifier(20), Sequence('%s_id_seq' % __tablename__), primary_key=True, nullable=False)
    jobs = relationship("EmployeeJob")
    roles = relationship("EmployeeRole")

class EmployeeJob(Base):
    __tablename__ = "t_employee_job"

    id = Column(Integer(20), Sequence('%s_id_seq' % __tablename__), primary_key=True, nullable=False)
    employee_id = Column(Integer(20), ForeignKey('t_employee.id', ondelete="CASCADE"), primary_key=True)
    job_id = Column(Integer(20), ForeignKey('t_job.id', ondelete="CASCADE"), primary_key=True)

class EmployeeRole(Base):
    __tablename__ = "t_employee_role"

    id = Column(Integer(20), Sequence('%s_id_seq' % __tablename__), primary_key=True, nullable=False)
    employee_id = Column(Integer(20), ForeignKey('t_employee.id', ondelete="CASCADE"), nullable=False)
    location_id = Column(Identifier(20), ForeignKey('t_location.id', ondelete="CASCADE"))
    role_id = Column(Integer(20), ForeignKey('t_role.id', ondelete="CASCADE"), nullable=False)

session.query(Employee).all()还检索角色和作业,但通过查询每行的数据库来实现。

我对这种情况有两个问题:
1. 在性能方面,我想我应该自己加入。我对么?
2.如何将表映射到某个数据结构?例如,我想获取具有角色的员工列表,其中每个角色应由位置 ID 和角色 ID 的数组表示,例如{id:1, jobs:[1,2,3], roles:[[1,1],[1,2],[2,3]]}

4

2 回答 2

2

1)请阅读SA 文档中的Eager Loading。默认情况下,关系在首次访问时会延迟加载。在您的情况下,您可以使用例如Joined Load,以便将相关行加载到同一查询中:

qry = (session.query(Employee).
       options(joinedload(Employee.jobs)).
       options(joinedload(Employee.roles))
      ).all()

如果您希望在加载 an 时始终加载这些关系Employee,您可以将 配置relationship为自动加载:

class Employee(Base):
    # ...
    jobs = relationship("EmployeeJob", lazy="joined")
    roles = relationship("EmployeeRole", lazy="subquery")

2)只需创建一个方法来从您的查询中提取数据结构。像下面这样的事情应该这样做(使用qry答案的第一部分):

def get_structure(qry):
    res = [{"id": e.id, 
            "jobs": [j.id for j in e.jobs],
            "roles": [[r.location_id, r.role_id] for r in e.roles],
            }
            for e in qry
            ]
    return res

另请注意:您的EmployeeJob表格有 fun primary_key,其中包括id列和两ForeignKey列。我认为你应该选择其中之一。

于 2013-03-04T09:45:57.143 回答
0

我终于找到了完成第二个问题的方法,并决定为他人的利益回答我自己的问题:

from sqlalchemy.ext.hybrid import hybrid_property

class Employee(Base):
    __tablename__ = "t_employee"

    id = Column(Identifier(20), Sequence('%s_id_seq' % __tablename__), primary_key=True, nullable=False)
    _jobs = relationship("EmployeeJob", lazy="joined", cascade="all, delete, delete-orphan")
    _roles = relationship("EmployeeRole", lazy="joined", cascade="all, delete, delete-orphan")

    @hybrid_property
    def jobs(self):
        return [item.employee_id for item in self._jobs]

    @jobs.setter
    def jobs(self, value):
        self._jobs = [EmployeeJob(job_id=id) for id in value]

    @hybrid_property
    def roles(self):
        return [[item.location_id, item.role_id] for item in self._roles]

    @roles.setter
    def roles(self, value):
        self._roles = [EmployeeRole(location_id=l_id, role_id=r_id) for l_id, r_id in value]

关系中的级联是为了确保一旦更新列表就删除孤儿,装饰器定义每个复杂属性的getter和setter

谢谢面包车给我指出正确的方向!

于 2013-03-07T12:16:57.733 回答