データベース構造
2 つの異なる関係を持つ 2 つのクラス A と B があります。
1) 関連付けテーブル (関連付け) を使用して、その特定の関連付け (association_property_1) のみに関連する情報を格納し、A および B の backref によってインスタンス化される多対多の関係。
2) table_b の外部キーを使用した A と B の 1 対 1 の関係 (この関係について B だけが「知っている」)。Aがそれを知っているかどうかは気にしませんが、この方法の方が簡単に思えました.
私のクラスは次のようになります。
class A(Base):
__tablename__ = 'table_a'
id = Column(Integer, primary_key=True)
a_property_1 = Column(Float)
a_property_2 = Column(Float)
a_property_special = Column(Float)
# Many-to-many relationship with B through an Association
associated_bs = relationship('Association', backref='a')
class B(Base):
__tablename__ = 'table_b'
id = Column(Integer, primary_key=True)
b_property_1 = Column(Float)
b_property_2 = Column(Float)
# One-to-one relationship with A
a_id = Column(Integer, ForeignKey('table_a.id'))
a = relationship('A', uselist=False, backref='b')
# Many-to-many relationship with A through an Association
associated_as = relationship('Association', backref='b')
class Association(Base):
__tablename__ = 'associations'
a_id = Column(Integer, ForeignKey('table_a.id'), primary_key=True)
b_id = Column(Integer, ForeignKey('table_b.id'), primary_key=True)
association_property_1 = Column(Float)
手順
Bとの1対1の関係を通じてAの特別なプロパティにアクセスできるすべての関連付けに対してクエリを実行したいので、基本的にプロパティにアクセスできるようにしたい
B.a.a_property_special
クエリ内。
特定のクエリの例は次のとおりです。
session.query(Association.association_property_1,
func.abs(A.a_property_special - B.a.a_property_special).\
filter(B.a.a_property_special > 3.0)
ここで、A と B は多対多の関係を使用して結合され、Ba は 1 対 1 で結合されます。B がインスタンス化されていないため、明らかにこのクエリは機能しないため、Baa_property_special にアクセスできません。
多対多の関係がなければ、B で A に参加するだけで完了できます。私の問題は、関連付けを使用して A と B の両方にクエリを実行したいということですが、1 対 1 の関係を介してスカラー Baa_property_special が必要です。
可能な解決策
私はいくつかの異なる解決策を試しましたが、さまざまな理由ですべてが不十分であることが判明しました.
- 列「a_property_special」をテーブル B にコピーします。これは、A と B の間の 1 対 1 の関係が変更された場合 (実行時に変更される可能性があります)、情報が複製され、適切な論理データ構造が表示されないため、私は好きではありません。
- column_property または association_proxy を使用します。きれいに見えますが、インスタンス化されたオブジェクトでしか正しく動作しません。それらをクエリで使用すると、バイナリ式の作成などで問題が発生します。
- サブクエリの使用。私はこれを少しいじりましたが、うまく機能するものを作成できませんでした。多分私はそれを正しくやっていないだけかもしれませんが、いつも非常に雑然として遅くなるようです.
- すべてのアソシエーションを照会し、Python で数学、論理式、およびフィルタリングを行うだけです。これはSQLで行うよりも効率が悪いと思いますが、間違っている可能性があります..
要件
- 高速である必要があります(当然)。私のテーブルには、それぞれ数倍の 100,000 レコードがあります。
- データベースの論理構造を反映しながら、デバッグや変更が容易になるように、クエリはできるだけ単純にする必要があります。クラス定義内にできるだけ多くのコードを隠しておきたいと思います。
- リレーションシップの構造について特に好みはありません。1対 1 と多対多 (独自の関連プロパティを含む) が必要なだけです。
これは本当に簡単だと思いますが、良い解決策が見つからないようです。ヘルプやコメントは大歓迎です。