1

sqlalchemyを使用して、科学的なテストデータを格納するデータベースを設計しています。私は理解できないような問題にぶつかりました。

私のテストデータでは、それぞれObservationState(位置、速度、加速度)がありState、に関連付けられたTime(状態が適用される時間)があります。ここまでは順調ですね。さまざまな時間に対応しているため、別のテーブルを作成しましTimesた。参照テーブルを使用して、毎回どのような時間(状態時間、観測時間など)であるかを示したいと思いました。また、処理する時間の種類が変わる可能性があるため、このように正規化すると、参照テーブルの行にすぎないため、将来的に新しい種類の時間を追加できるようになると思います。

これまでのところ、この部分は機能します(宣言型スタイルを使用):

class Observation(Base):
    __tablename__ = 'tbl_observations'
    id = Column(Integer, primary_key=True)
    state_id = Column(Integer, ForeignKey('tbl_states.id'))
    state = relationship('State', uselist=False)

class State(Base):
    __tablename__ = 'tbl_states'
    id = Column(Integer, primary_key=True)
    time_id = Column(Integer, ForeignKey('tbl_times.id'))
    time = relationship('Time', uselist=False)

class Time(Base):
    __tablename__ = 'tbl_times'
    id = Column(Integer, primary_key=True)
    time_type_id = Column(Integer, ForeignKey('ref_tbl_time_types.id'))
    time_type = relationship('TimeType', uselist=False)
    time_value = Column(Float)

class TimeType(Base):
    __tablename__ = 'ref_tbl_time_types'
    id = Column(Integer, primary_key=True)
    desc = Column(String)

しわは、観察自体が異なる種類の時間を持っている可能性があるということです。との間に1対多の関係を作成しようとするObservationTime、循環依存エラーが発生します。

class Observation(Base):
    __tablename__ = 'tbl_observations'
    id = Column(Integer, primary_key=True)
    state_id = Column(Integer, ForeignKey('tbl_states.id'))
    state = relationship('State', uselist=False)

    # Added this line:
    times = relationship('Time')

class Time(Base):
    __tablename__ = 'tbl_times'
    id = Column(Integer, primary_key=True)
    time_type_id = Column(Integer, ForeignKey('ref_tbl_time_types.id'))
    time_type = relationship('TimeType', uselist=False)
    time_value = Column(Float)

    # Added this line:
    observation_id = Column(Integer, ForeignKey('tbl_observations.id'))

Observation元の-> State->Timeチェーンには。までの参照があるため、これは壊れていると思いObservationます。

これを修正する方法はありますか?私は自分のデザインをすべて台無しにしてしまいましたか?sqlalchemyで何か間違ったことをしていますか?私はこれらすべてに不慣れなので、上記のいずれかである可能性があります。あなたが与えることができるどんな助けでも非常にありがたいです。

PSここで推奨されていることを実行しようとしました:循環参照を回避しようとしましたが、間違って実行したか、特定の問題が解決しませんでした。

4

3 に答える 3

4

ユースケースの再検討に関する他の回答は貴重であり、それらを検討する必要があります。ただし、SQLAlchemyに関する限り、複数のFKによる循環依存の問題は、http://docs.sqlalchemy.org/en/rel_0_7/orm/relationships.html#rows-に記載されているuse_alter/post_updateの組み合わせによって解決されます。 that-point-to-themself-mutually-dependent-rows。これを使用したモデルは次のとおりです。

from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base

Base= declarative_base()

class Observation(Base):
    __tablename__ = 'tbl_observations'
    id = Column(Integer, primary_key=True)
    state_id = Column(Integer, ForeignKey('tbl_states.id'))
    state = relationship('State', uselist=False)

    times = relationship('Time')

class State(Base):
    __tablename__ = 'tbl_states'
    id = Column(Integer, primary_key=True)
    time_id = Column(Integer, ForeignKey('tbl_times.id'))

    # post_update is preferable on the many-to-one
    # only to reduce the number of UPDATE statements
    # versus it being on a one-to-many.
    # It can be on Observation.times just as easily.
    time = relationship('Time', post_update=True)

class Time(Base):
    __tablename__ = 'tbl_times'
    id = Column(Integer, primary_key=True)
    time_type_id = Column(Integer, ForeignKey('ref_tbl_time_types.id'))
    time_type = relationship('TimeType', uselist=False)
    time_value = Column(Float)

    observation_id = Column(Integer, ForeignKey('tbl_observations.id', 
                                    use_alter=True, name="fk_time_obs_id"))

class TimeType(Base):
    __tablename__ = 'ref_tbl_time_types'
    id = Column(Integer, primary_key=True)
    desc = Column(String)


e = create_engine("postgresql://scott:tiger@localhost/test", echo=True)
Base.metadata.drop_all(e)
Base.metadata.create_all(e)

s = Session(e)

tt1 = TimeType(desc="some time type")
t1, t2, t3, t4, t5 = Time(time_type=tt1, time_value=40), \
                Time(time_type=tt1, time_value=50), \
                Time(time_type=tt1, time_value=60),\
                Time(time_type=tt1, time_value=70),\
                Time(time_type=tt1, time_value=80)

s.add_all([
    Observation(state=State(time=t1), times=[t1, t2]),
    Observation(state=State(time=t2), times=[t1, t3, t4]),
    Observation(state=State(time=t2), times=[t2, t3, t4, t5]),
])

s.commit()
于 2012-06-12T23:01:27.700 に答える
2

オブザベーションとステートの間には多対1の関係があります。したがって、1つの状態に多くの観測値を含めることができ、すべての観測値に1つの状態があります。

また、StatesとTimesの間には多対1の関係があります。したがって、1回の時間には多くの状態があり、すべての状態に1つの時間があります。

問題はタイムズからの観測への参照であるという点であなたは正しいです。あなたは毎回観測を強制し、それは順番に状態を持たなければならず、それは順番に時間を持たなければなりません(そしてループは永遠に繰り返されます)。

これを打破するには、これらの関係で実際に何を表現しようとしているのかを理解する必要があります。オブザベーションに時間がある状態がある場合、オブザベーションには時間があります(状態から時間を取得できます)。

ですから、あなたが答える必要のある本当の質問は、次のとおりです。時間には観察があるとはどういう意味ですか?アプリケーションでそれをどのように使用しますか?

于 2012-06-07T20:11:43.943 に答える
0

オブジェクトモデルのモデル名と、それらが実際の世界にどのように対応しているかを完全に把握しているわけではないと思います。しかし、私は推測しようとします。まず、モデルTime(かなり基本的でほとんどロジックがないように見えます)ForeignKeyに、より高いレベルのモデルクラスが必要かどうかは疑問ですObservation。これに照らして、私はあなたのモデルをn-1関係の連鎖としてではなく、むしろ一種の三項関係として見ています。だから私はあなたが次のようなモデルを見ることができました:

class Base(object):
    id = Column(Integer, primary_key=True)

class Observation(Base):
    __tablename__ = 'tbl_observations'

class ObservationInstance(Base):
    __tablename__ = 'tbl_observation_instances'
    observation_id = Column(Integer, ForeignKey('tbl_observations.id'))
    state_id = Column(Integer, ForeignKey('tbl_states.id'))
    time_id = Column(Integer, ForeignKey('tbl_times.id'))

    # relationships
    observation = relationship('Observation', backref="instances")
    state = relationship('State')
    time = relationship('Time')

class State(Base):
    __tablename__ = 'tbl_states'

class Time(Base):
    __tablename__ = 'tbl_times'
    time_type_id = Column(Integer, ForeignKey('ref_tbl_time_types.id'))
    time_type = relationship('TimeType', uselist=False)
    time_value = Column(Float)

class TimeType(Base):
    __tablename__ = 'ref_tbl_time_types'
    desc = Column(String)

これが理にかなっていて、モデル化しようとしている現実の世界に適合することを願っています。あなたのモデルはある種の(科学的な)実験を表していると思いました。この場合、名前を変更Observation -> ExperiementしてObservationInstance -> Observation

于 2012-06-08T20:36:52.723 に答える