2012-06-07 2 views
1

저는 sqlalchemy를 사용하여 과학적 테스트 데이터를 저장할 데이터베이스를 설계하고 있습니다. 내가 알아낼 수없는 문제를 쳤다. 내 테스트 데이터세 테이블 간의 순환 종속성을 피하십시오

ObservationState (위치, 속도, 가속도)을 가지며,이 연관된 StateTime (상태가 적용되는 시간)을 갖는다. 여태까지는 그런대로 잘됐다. 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) 

주름은 스스로 관찰 시간의 다른 종류를 가질 수 있다는 것입니다. ->State ->Time 체인입니다있다

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이 때문에 나누기 같은데요 : 내가 ObservationTime 사이에 일대 다 관계를 만들려고 할 때, 나는 순환 종속성 오류가 참조 바로 뒤로 최대 Observation.

이 문제를 해결할 방법이 있습니까? 내 디자인이 엉망이 됐어? sqlalchemy에서 잘못된 것이 있습니까? 나는이 모든 것에 익숙하지 않으므로 위의 것들 중 하나 일 수 있습니다. 당신이 줄 수있는 도움은 대단히 감사하겠습니다.

P. 나는 여기에서 추천되었던 것을했다. Trying to avoid a circular reference 그러나 나는 그것을 잘못했다. 그렇지 않으면 나의 특별한 문제를 해결하지 못했다.

답변

4

유스 케이스의 재검토와 관련하여 다른 답변은 가치가 있으므로 고려해야합니다. 그러나 SQLAlchemy에 관한 한 다중 FK로 인한 순환 종속성 문제는 use_alter/post_update 조합으로 해결됩니다 (http://docs.sqlalchemy.org/en/rel_0_7/orm/relationships.html#rows-that-point-to-themselves-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:[email protected]/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() 
+0

이것은 굉장합니다. 해당 소프트웨어를 만든 사람이 제공 한 소프트웨어 패키지에 대한 질문에 대한 자세한 개인화 된 답을 얻을 수있는 곳은 어디입니까? 감사합니다 마이크! – IanVS

2

관측과 국가 간에는 많은 관계가 있습니다. 그래서 한 국가는 많은 관찰을 할 수 있고 모든 관찰은 하나의 국가를가집니다.

또한 상태와 시간 사이에 여러 관계가 있습니다. 따라서 하나의 시간은 많은 국가를 가질 수 있으며, 모든 국가는 하나의 시간을가집니다.

문제점은 Times의 관측에 대한 참조라는 점에서 정확합니다. 각 시간마다 관찰이 필요하며 차례로 상태가 있어야하며 차례대로 시간이 있어야합니다 (루프가 영원히 반복됩니다).

이 문제를 해결하려면 이러한 관계에서 실제로 묘사하려는 것을 파악해야합니다. 관측치에 시간이있는 주 (State)가있는 경우 관측에는 시간이 있습니다 (주에서 시간을 얻을 수 있음).

그래서 여러분이 대답해야 할 실제 질문은 : 시간에 관찰이 있다고 말하는 것은 무엇을 의미합니까? 귀하의 응용 프로그램에서 어떻게 사용 하시겠습니까?

+0

감사합니다. 제가 의도 한 바는 관측과 국가 간, 그리고 국가와 시간 사이의 일대일입니다. 잘못 코딩 한 경우 나를 도와주세요. 나는 유령론 = True가 내가 그것을 일대일로 만드는 방법이라고 생각했습니다. Observations와 Times 사이에는 일대일이 필요합니다. Observations와 Times는 여러 가지 종류의 시간대를 관찰 할 수 있습니다. – IanVS

+0

@IanVS - 여기에 sqlalchemy의 관계에 대한 링크가 있습니다. http://docs.sqlalchemy.org/en/rel_0_7/orm/relationships.html 나는 그것을 직접 사용하지 않았기 때문에 모든 것이 어떻게 작동하는지 정확히 알지 못합니다. , 그러나 이것은 다양한 종류의 관계를 설정하는 방법에 대한 좋은 지침서입니다. – Caleb

+0

@IanVS - 말하자면, 나는 당신이 묘사하는 방식으로 여전히 관계를 만드는 데 문제가 있다고 생각합니다. Observations를 Times에 두 가지 다른 방식으로 연결하여 계속 원을 만듭니다. States를 Times에 의존시키지 않거나 Observations를 Times에 종속시키지 않거나 Observations를 States에 의존하지 않도록해야합니다. 응용 프로그램에서 이러한 개체가 실제로 무엇을 의미하는지 모르겠으므로 관련성을 알 수 없습니다. 그러나 객체가 어떻게 하나의 "시간"을 가진 무언가와 관련 될 수 있는지를 이해하지 못하고 또한 많은 "시간"을 가지고 있습니다. – Caleb

0

개체 모델에서 모델 이름을 완전히 얻지 못했고 실제 모델과 어떻게 일치하는지 모릅니다. 그러나 나는 추측하려고 노력할 것이다. 먼저 모델 Time (다소 기본적이고 거의 로직이 아닌 것처럼 보임)이 ForeignKey의 상위 모델 클래스 Observation에 있어야한다고 생각합니다. 이 점에 비추어, 당신의 모델이 n-1 관계의 체인이 아니라, ternary relationship의 종류라고 봅니다.그래서 난 당신이 다음과 같이 모델링 볼 수 있습니다 :

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 -> ExperiementObservationInstance -> Observation으로 이름을 바꿉니다.

+0

도움 주셔서 감사합니다. 나는 내가 보지 못하는 것 (그리고 아마도 그것을 놓치고있다)을 추측한다. ObservationInstance를 시간 (관찰 시간이라고 부름)과 상태를 다른 시간 (상태 시간)과 관련시킬 수있는 방법이다. 필자는 예제를 간소화했지만 실제로는 미래에 여러 번 "예측 된"상태가있을 수 있습니다. 따라서 관측치에는 하나의 관측 시간과 각각의 상태 시간을 가진 다중 상태가 있습니다. 위의 디자인이 이것을 지원합니까? – IanVS

+0

@IanVS : 귀하의 모델에있는 문제가 명명 과정에서 보여지는 것처럼 보입니다. 시간은 상태가 아니며 상태도 없습니다. 국가는 사건 일 때가 아니라 사건 일 때가 있기 때문에 시간이 없다. 둘 다 연결되는 사건으로 인해 시간과 주체가 관련이없는 엔티티가 있습니까? – reinierpost

+0

@reinierpost : 상태는 관련 시간없이 유효하지 않으므로 국가에 시간이 없다고 말하는 이유는 무엇입니까? 아마도 그것은 내 설명에서 불분명하다. 제 경우의 '상태'는 특정 시간에 위치, 속도 및 가속도입니다. 그런 식으로 생각하면 아마도 'valid_time'열을 'state'에 추가하고 'time' 테이블 만'observation '과 관련되게 만드는 것이 더 합리적 일 것입니다. – IanVS

관련 문제