2009-08-26 17 views
43

मैं स्क्लेल्चेमी के तहत विरासत के बारे में थोड़ा उलझन में हूं, इस बिंदु पर जहां मुझे यह भी सुनिश्चित नहीं है कि किस तरह की विरासत (एकल तालिका, तालिका में शामिल, ठोस) मुझे यहां उपयोग करना चाहिए। मुझे कुछ जानकारी के साथ बेस क्लास मिला है जो सबक्लास के बीच साझा किया गया है, और कुछ डेटा जो पूरी तरह से अलग हैं। कभी-कभी, मैं सभी वर्गों से डेटा और कभी-कभी केवल उप-वर्गों से डेटा चाहता हूं। यहां एक उदाहरण दिया गया है:SQLAlchemy विरासत

class Building: 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

class Commercial(Building): 
    def __init__(self, x, y, business): 
     Building.__init__(self, x, y) 
     self.business = business 

class Residential(Building): 
    def __init__(self, x, y, numResidents): 
     Building.__init__(self, x, y, layer) 
     self.numResidents = numResidents 

मैं इसे घोषणात्मक का उपयोग करके एसक्यूएलकेमी में कैसे परिवर्तित करूं? तो, मैं पूछूंगा कि कौन सी इमारतें x>5 और y>3 के भीतर हैं? या कौन सी आवासीय इमारतों में केवल 1 निवासी है?

उत्तर

68

विरासत का प्रतिनिधित्व करने का तरीका चुनना ज्यादातर डेटाबेस डिज़ाइन मुद्दा है। प्रदर्शन के लिए एकल टेबल विरासत आमतौर पर सबसे अच्छा है। एक अच्छी डेटाबेस डिजाइन बिंदु से, तालिका विरासत में शामिल होना बेहतर है। तालिका तालिका में शामिल होने से आपको डेटाबेस द्वारा लागू उप-वर्गों के लिए विदेशी कुंजी प्राप्त करने में सक्षम बनाता है, उप-वर्ग फ़ील्ड के लिए गैर-शून्य बाधाओं के लिए यह बहुत आसान है। कंक्रीट टेबल विरासत दोनों दुनिया के सबसे खराब है। इस तरह कथात्मक दिखता साथ

एकल तालिका भाग सेटअप:

class Building(Base): 
    __tablename__ = 'building' 
    id = Column(Integer, primary_key=True) 
    building_type = Column(String(32), nullable=False) 
    x = Column(Float, nullable=False) 
    y = Column(Float, nullable=False) 
    __mapper_args__ = {'polymorphic_on': building_type} 

class Commercial(Building): 
    __mapper_args__ = {'polymorphic_identity': 'commercial'} 
    business = Column(String(50)) 

class Residential(Building): 
    __mapper_args__ = {'polymorphic_identity': 'residential'} 
    num_residents = Column(Integer) 

यह मेज विरासत में शामिल हो गए हैं, आप उपवर्गों

__tablename__ = 'commercial' 
id = Column(None, ForeignKey('building.id'), primary_key=True) 

जोड़ने की आवश्यकता होगी।

क्वैरी ज्यादातर दोनों दृष्टिकोण के साथ एक ही है:

# buildings that are within x>5 and y>3 
session.query(Building).filter((Building.x > 5) & (Building.y > 3)) 
# Residential buildings that have only 1 resident 
session.query(Residential).filter(Residential.num_residents == 1) 

नियंत्रित करने के लिए जो खेतों आप query.with_polymorphic() विधि का उपयोग कर सकते हैं लोड किए गए हैं।

डाटामैपिंग के लिए विरासत का उपयोग करने के बारे में सोचने की सबसे महत्वपूर्ण बात यह है कि क्या आपको वास्तव में विरासत की आवश्यकता है या एकत्रीकरण के साथ कर सकते हैं। विरासत एक दर्द होगा यदि आपको कभी भी किसी भवन के प्रकार को बदलने की आवश्यकता होगी, या आपकी इमारतों में वाणिज्यिक और आवासीय दोनों पहलू हो सकते हैं। उन मामलों में वाणिज्यिक वस्तुओं और आवासीय पहलुओं को संबंधित वस्तुओं के रूप में आमतौर पर बेहतर होता है।

+2

वाह, यह एक अच्छा जवाब है। धन्यवाद! तो मैंने एकल और जुड़ने वाले टेबल विकल्पों के बीच प्रदर्शन की तुलना की है, और दूसरी क्वेरी [फ़िल्टर (Residential.num_residents == n) .count()] एकल तालिका परिदृश्य (अपेक्षित के रूप में) में ~ 2x तेज चलाता है। हालांकि, किसी कारण से बिल्डिंग [फ़िल्टर ((बिल्डिंग.एक्स> एक्स) और (बिल्डिंग.ए> वाई)) के खिलाफ पहली क्वेरी। गिनती()] एकल तालिका के साथ लगभग 10% धीमी है, हालांकि वास्तव में सभी तत्वों को लोड करना बहुत तुलनीय है (.all())। – Noah

+0

शामिल तालिका विरासत के संबंध में एक और विशिष्ट समस्या के लिए http: // stackoverflow देखें।कॉम/प्रश्न/838 9 606/कैसे-कर-ए-एसक्लाल्चेमी-क्लास-वारिस-ठीक-बावजूद-एक-मुश्किल-विदेशी-आर –

+1

एकमात्र चीज गायब है कंक्रीट टेबल विरासत का उपयोग करके एक उदाहरण है - जिसे मैं चाहता हूं स्वाभाविक रूप से मदद करें :-) चूंकि यह एक पुराना सवाल है, इसलिए इस प्रश्न का उत्तर देने के बाद ठोस तालिका विरासत जोड़ा गया था। – ThatAintWorking

10

चींट्स अजामा का समाधान अधिक सुरुचिपूर्ण है, लेकिन यदि आप अपनी कक्षा परिभाषाओं को जानबूझकर अपनी तालिका परिभाषाओं से अलग रखते हैं, तो आपको मैपर फ़ंक्शन के साथ अपनी कक्षाओं को अपनी तालिकाओं में मैप करना होगा। के बाद आप अपनी कक्षाओं को परिभाषित किया है, तो आप अपने टेबल निर्धारित करने होंगे:

building = Table('building', metadata, 
    Column('id', Integer, primary_key=True), 
    Column('x', Integer), 
    Column('y', Integer), 
) 
commercial = Table('commercial', metadata, 
    Column('building_id', Integer, ForeignKey('building.id'), primary_key=True), 
    Column('business', String(50)), 
) 
residential = Table('residential', metadata, 
    Column('building_id', Integer, ForeignKey('building.id'), primary_key=True), 
    Column('numResidents', Integer), 
)

तो फिर तुम वर्गों के लिए टेबल मैप कर सकते हैं:

mapper(Building, building) 
mapper(Commercial, commercial, inherits=Building, polymorphic_identity='commercial') 
mapper(Residential, residential, inherits=Building, polymorphic_identity='residential')

फिर वर्गों के साथ ठीक उसी तरह से चींटियों आसमा वर्णित बातचीत ।