以下是设置:
有车的任务(例如从A点到B点) - 名为使命的模型。
Mission汽车(型号名为 Car )按日期版本(见下面的型号)
汽车有一个GPS设备(型号名为 GPS ),用于发送信号 当前位置。 GPS设备也按日期进行版本化(参见下面的模型)。
GPS设备与汽车(型号 CArGPS )的附件也会进行版本控制 (见下面的模型) (是的,它非常复杂,我无法改变架构。)
问题:这样设置关系,所以我可以获得任务的版本 汽车(通过 Mission.date_start )并获得附加到这辆车的gps设备版本 版本(通过 Mission.date_start )。
如果是SQL,那就是:
SELECT
mission.id AS mission_id,
mission.date_start AS mission_date_start,
mission.car_id AS mission_car_id,
car_1.id AS car_1_id,
car_1.car_id AS car_1_car_id,
car_1.start_date AS car_1_start_date,
car_1.end_date AS car_1_end_date,
car_1.version_start_date AS car_1_version_start_date,
car_1.version_end_date AS car_1_version_end_date,
car_gps_1.id AS car_gps_1_id,
car_gps_1.gps_id AS car_gps_1_gps_id,
car_gps_1.car_id AS car_gps_1_car_id,
car_gps_1.start_date AS car_gps_1_start_date,
car_gps_1.end_date AS car_gps_1_end_date,
gps_1.gps_code AS gps_1_gps_code
FROM mission
LEFT OUTER JOIN car AS car_1 ON car_1.car_id = mission.car_id AND
car_1.start_date <= mission.date_start AND
car_1.end_date >= mission.date_start AND
car_1.version_start_date <= mission.date_start AND
car_1.version_end_date >= mission.date_start
LEFT OUTER JOIN car_gps AS car_gps_1 ON car_gps_1.car_id = mission.car_id AND
car_gps_1.start_date <= mission.date_start AND
car_gps_1.end_date >= mission.date_start
LEFT OUTER JOIN gps as gps_1 ON gps_1.id = car_gps_1.id AND
gps_1.start_date <= mission.date_start AND
gps_1.end_date >= mission.date_start
所以我想查询,比如
query = session.query(Mission).options(
joinedload(Mission.car), joinedload(Mission.car_device)
)
results = query.all()
# and get gps code of mission car
gps_code = query.Mission.car_device.gps_code
模型代码等:
class GPS(Base):
'''Version of gps-device'''
__tablename__ = 'gps'
id = Column(Integer(), primary_key=True)
gps_id = Column(Integer(), primary_key=True)
start_date = Column(Date(), primary_key=True)
end_date = Column(Date(), primary_key=True)
gps_code = Column(VARCHAR(20))
class Car(Base):
'''Version of car'''
__tablename__ = 'car'
id = Column(Integer(), primary_key=True)
car_id = Column(Integer(), primary_key=True)
start_date = Column(Date(), primary_key=True)
end_date = Column(Date(), primary_key=True)
version_start_date = Column(Date(), primary_key=True)
version_end_date = Column(Date(), primary_key=True)
class CarGPS(Base):
'''Version of attachment of gps-device to car'''
__tablename__ = 'car_gps'
id = Column(Integer(), nullable=False)
gps_id = Column(Integer(), ForeignKey(GPS.gps_id), primary_key=True)
car_id = Column(Integer(), ForeignKey(Car.car_id), primary_key=True)
start_date = Column(TIMESTAMP(timezone=True), primary_key=True)
end_date = Column(TIMESTAMP(timezone=True), primary_key=True)
class Mission(Base):
'''Car mission'''
__tablename__ = 'mission'
id = Column(Integer(), primary_key=True, nullable=False)
date_start = Column(TIMESTAMP(timezone=False))
car_id = Column(Integer(), ForeignKey(Car.id))
# Version of mission car
car = relationship(Car,
primaryjoin=and_(Car.car_id == car_id,
Car.start_date <= date_start,
Car.end_date >= date_start,
Car.version_start_date <= date_start,
Car.version_end_date >= date_start),
foreign_keys=car_id,
uselist=False, viewonly=True)
# Version of mission car gpd-device attachment
car_gps = relationship(CarGPS,
primaryjoin=and_(CarGPS.car_id == car_id,
CarGPS.start_date <= date_start,
CarGPS.end_date >= date_start),
foreign_keys=CarGPS.car_id,
uselist=False, viewonly=True)
Session = sessionmaker(bind=engine)
session = Session()
Base.metadata.create_all(engine)
# This query is good but without GPS device of car
query = session.query(Mission).options(
joinedload(Mission.car), joinedload(Mission.car_gps)
)
query.all()
我是sqlAlchemy的新手,无法理解如何设置此类关系 GPS设备。也许可以使用secondary和secondaryjoin来实现 关系的属性?
目前可以通过此查询实现:
query = query.outerjoin(CarGPS, and_(
CarGPS.car_id == Mission.car_id,
CarGPS.start_date <= Mission.date_start,
CarGPS.end_date >= Mission.date_start))
query = query.outerjoin(
GPS, and_(GPS.gps_id == CarGPS.gps_id,
GPS.start_date <= Mission.date_start,
GPS.end_date >= Mission.date_start))
但我想通过关系来做,而不是通过join / outerjoin。 谢谢!
SQLAlchemy版本:sqlalchemy == 1.0.14
Python版本:3.5.1