Son zamanlarda tırmanma alanları ve yolları içeren bir proje için SQL Alchemy ile çalışmaya başladı. Alanlar hiyerarşiktir, çünkü tek bir alan birden fazla alan içerebilir ve bu da diğer alanları içerebilir. Bir yol doğrudan tek bir alanla ilişkilendirilir, ancak aynı zamanda o alanın ebeveyni vb. Ile de ilişkilidir.SQL Alchemy Closure Tablo İlişki Tanımı
Bunu uygulamak için bir closure table ala Bill Karwin kullanmayı seçtim. Kapatma tablosu uygulamasında, atası/iniş bilgisini saklamak için ikinci bir tablo oluşturulur. Bir düğüm eklendiğinde, bir öz referanslama satırı ve ayrıca ağaçtaki her ata için bir satır oluşturulur. aşağıdaki gibi
tablo yapısı (basitleştirilmiş) olduğu:
-- area --
area_id
name
-- area_relationship --
ancestor
descendent
-- route --
route_id
area_id
name
Örnek veri:
-- area --
1, New River Gorge
2, Kaymoor
3, South Nuttall
4, Meadow River Gorge
-- area_relationship (ancestor, descendent) --
1, 1 (self-referencing)
2, 2 (self-referencing)
1, 2 (Kaymoor is w/i New River Gorge)
3, 3 (self-referencing)
1, 3 (South Nutall is w/i New River Gorge)
4, 4 (self-referencing)
-- route (route_id, area_id, name)
1, 2, Leave it to Jesus
2, 2, Green Piece
3, 4, Fancy Pants
(ağacın kadar) belirli bir rota için tüm alanlar için sorgulamak için, ben yürütebilirsiniz:
SELECT area.area_id, area.name
FROM route
INNER JOIN area_relationship ON route.area_id = area_relationship.descendent
INNER JOIN area ON area.area_id = area_relationship.ancestor
WHERE route.route_id = 1
Benzer şekilde, belirli bir alandaki (alçalma alanları dahil) tüm rotaları şu şekilde sorgulayabilirim: -
class DbArea(Base):
__tablename__ = 'area'
area_id = Column(Integer, primary_key = True)
name = Column(VARCHAR(50))
created = Column(DATETIME)
area_relationship_table.c.ancestor])
descendents = relationship('DbArea', backref = 'ancestors',
secondary = area_relationship_table,
primaryjoin = area_id == area_relationship_table.c.ancestor,
secondaryjoin = area_id == area_relationship_table.c.descendent)
DbRoute sınıfı -
class DbRoute(Base):
__tablename__ = 'route'
route_id = Column(Integer, primary_key = True)
area_id = Column(Integer, ForeignKey('area.area_id'))
name = Column(VARCHAR(50))
created = Column(DATETIME)
area = relationship("DbArea")
areas = relationship('DbArea', backref = 'routes',
secondary = area_relationship_table,
primaryjoin = area_id == area_relationship_table.c.ancestor,
secondaryjoin = area_id == area_relationship_table.c.descendent,
foreign_keys=[area_relationship_table.c.ancestor,
area_relationship_table.c.descendent])
area_relationship_table = Table('area_relationship', Base.metadata,
Column('ancestor', Integer, ForeignKey('area.area_id')),
Column('descendent', Integer, ForeignKey('area.area_id'))
)
DbArea sınıfı: Ben bu ilişkileri işlemek için bir ilişki ve iki tablo oluşturduk SQL Simyada
SELECT route.route_id, route.name
FROM area
INNER JOIN area_relationship ON area.area_id = area_relationship.ancestor
INNER JOIN route ON route.area_id = area_relationship.descendent
WHERE area.area_id = 1
Şu anda, ben DbRoute'daki bölgeler ilişkisini kullanarak, tekil güzergahtaki alanları belirleyebilme. Ancak, ben DbArea içinde backref 'yolları' kullanmayı deneyin, aşağıdaki hatayı alıyorum:
sqlalchemy.exc.StatementError: Hayır sütun route.area_id mapper Mapper yapılandırılır | DbArea | alan ... (orijinal Nedeni: UnmappedColumnError: Eşleştirilmemiş Mapper | DbArea | alanı üzerinde route.area_id sütun yok ...) 'route.route_id AS route_route_id, route.area_id AS route_area_id, route.name, route_name, route.created AS route_created \ nFROM route , area_relationship \ nWHERE% s = alan_relationship.descendent VE route.area_id = alan_relationship.ancestor '[immutabledict ({})]
Sanırım ilişkiyi kurmak için DbArea'ya bir şey eklemem gerekiyor sanırım, ama sonra bazı farklı seçeneklerle deneme yapmak, çözümü belirleyemedi.