2

私は Flask-SQLAlchemy を使用して Flask で作業しており、多対多対多の関係を設定しようとしています。クライアントは複数の注文を持つことができ、注文は複数のクライアント (多対多) を持つこともできます。各注文には、一意のアイテムのリストが含まれています (1 対多)。

SQLAlchemy のドキュメントに従って、多対多の関係の関連付けテーブルをセットアップし、1 対多の関係には通常の関係/外部キーを使用しました。すべての参照は に設定されlazy='dynamic'ます。

association_table = Table('association', Base.metadata,
Column('left_id', Integer, ForeignKey('left.id')),
Column('right_id', Integer, ForeignKey('right.id'))
)

itemsクライアントに関連付けられたすべてを取得する効率的な方法は何ですか? うまく[item for item in order.items.all() for order in client.orders]いくと思いますが(上記の問題は少ない)、もっと効率的な方法はありますか?結果を並べ替える必要がある場合はどうなりますか?


アップデート

次の 2 つの方法 (Audrius の回答の最初の方法) によって、クライアントの注文のアイテムを取得する 2 つの方法を知っています。

db.session.query(Item).\
    join(Order).join(Order.clients).\
    filter(Client.id == 42).\
    order_by(Item.timestamp)

Item.query.filter(Item.order_id._in(client.order_ids)).order_by(Item.timestamp)‌​

どちらも同じ結果が得られると思いますが、効率のためにどちらを優先する必要がありますか?

4

1 に答える 1

1

SQL でクエリを直接記述する場合、結合を使用して必要なデータを効率的に取得します (Rachcha が回答で示したように)。同じことが SQLAlchemy にも当てはまります。join()その他の例については、SA のドキュメントを参照してください。

モデルが次のように定義されている場合 (Flask-SQLAlchemy を使用して、質問にそのタグをタグ付けしたため):

clients_orders = db.Table('clients_orders',
    db.Column('client_id', db.Integer, db.ForeignKey('client.id'),
              primary_key=True),
    db.Column('order_id', db.Integer, db.ForeignKey('order.id'),
              primary_key=True)
)

class Client(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    orders = db.relationship('Order', secondary=clients_orders,
                             backref='clients')
    # Define other columns...

class Order(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    # Define other columns...

class Item(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False)
    order = db.relationship('Order', backref='items')
    timestamp = db.Column(db.DateTime)
    # Define other columns...

次に、クエリは次のようになります。

db.session.query(Item).\
    join(Order).join(Order.clients).\
    filter(Client.id == 42).\
    order_by(Item.timestamp)
于 2013-03-17T14:29:03.530 に答える