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()ロールとジョブも取得しますが、各行のデータベースにクエリを実行して取得します。

この状況について 2 つの質問があり
ます。 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()

がロードされるときに常にこれらの関係をロードする場合は、が自動的にロードされる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

また、注意してください:あなたのテーブルには、列と2つの列の両方を含むEmployeeJob面白いがあります。どちらかを選ぶべきだと思います。primary_keyidForeignKey

于 2013-03-04T09:45:57.143 に答える
0

私はついに私の2番目の問題を達成する方法を見つけ、他の人の利益のために自分の質問に答えることに決めました。

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]

関係のカスケードは、リストが更新されたときに孤立が削除され、デコレータが各複雑なプロパティのゲッターとセッターを定義することを保証することです。

私を正しい方向に向けてくれてありがとうバン!

于 2013-03-07T12:16:57.733 に答える