2010-09-09 19 views
15

मेरे पास एक मॉडल House है जिसमें कई बूलियन गुण हैं, जैसे has_fireplace, has_basement, has_garage, और इसी तरह। House में लगभग 30 ऐसे बूलियन गुण हैं। कुशल डेटाबेस भंडारण और खोज के लिए इस मॉडल को ढांचा बनाने का सबसे अच्छा तरीका क्या है?रेल में, मॉडल में एकाधिक बूलियन विशेषताओं को स्टोर करने का सबसे अच्छा तरीका क्या है?

मैं आखिरकार सभी Houses खोजना चाहता हूं जिसमें फायरप्लेस और गेराज है, उदाहरण के लिए।

बेवकूफ तरीका, मुझे लगता है कि मॉडल में 30 कॉलियन विशेषताओं को जोड़ना होगा जो प्रत्येक डेटाबेस में एक कॉलम से मेल खाते हैं, लेकिन अगर मैं रेल की सबसे अच्छी प्रैक्टिस करता हूं तो मुझे उत्सुकता है।

उत्तर

15

आपकी 'बेवकूफ' धारणा सही है - क्वेरी गति और उत्पादकता परिप्रेक्ष्य का सबसे प्रभावी तरीका प्रत्येक ध्वज के लिए कॉलम जोड़ना है।

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

+2

सहमत हुए। यदि आप चाहें, तो घर से संबंधित एक अलग मॉडल में सभी बूलियन होने के लिए यह बहुत आसान हो सकता है, जैसे घर है_one: feature_set (या कुछ), और फीचर सेट में सभी बूलियन हैं। फिर आप कुछ चीनी के लिए वर्चुअल एट्रिब्यूट का उपयोग कर सकते हैं, जैसे हाउस मॉडल def has_fireplace ?; self.feature_set.fireplace; अंत –

+0

धन्यवाद, यहोशू और जॉन। जॉन, क्या अलग-अलग बनाने में बड़ी जीत है: फीचर_सेट मॉडल सभी बूलियन स्टोर करने के लिए? क्या आप दृढ़ मॉडल डिजाइन की दृढ़ता से अनुशंसा करेंगे? क्योंकि यदि नहीं, तो मुझे लगता है कि मैं सिर्फ यहोशू के "घरों में कॉलम जोड़ना" दृष्टिकोण के साथ जाऊंगा। – Sanjay

+0

नहीं, संगठनात्मक कारणों को छोड़कर चीजों को अलग करने का कोई वास्तविक कारण नहीं है, अगर आपको अपना "घर" मॉडल बहुत गन्दा हो रहा है तो बस एक विकल्प। –

0

आपके पास हमेशा एक टेक्स्ट कॉलम हो सकता है जिसमें आप JSON रखते हैं (कहें, data), और फिर आपके प्रश्न SQL की पसंद का उपयोग कर सकते हैं।

उदाहरण के लिए: house.data # => '{ "has_fireplace": सच है, "has_basement": झूठे, "has_garage": सच}'

इस प्रकार, कर एक LIKE '%"has_fireplace":true%' का उपयोग कर एक चिमनी के साथ कुछ भी वापसी होगी लगता है ।

मॉडल संबंधों का उपयोग करना (उदाहरण के लिए, केवल घर के अलावा फायरप्लेस, बेसमेंट और गेराज के लिए एक मॉडल) इस मामले में बेहद बोझिल होगा, क्योंकि आपके पास बहुत सारे मॉडल हैं।

+2

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

6

एक ही मॉडल में कई बूलियन के लिए आप मूल्यों का प्रतिनिधित्व, संग्रह और पुनर्प्राप्ति के लिए एक पूर्णांक और बिटवाई ऑपरेशंस का उपयोग करने पर विचार कर सकते हैं। उदाहरण के लिए:

class Model < ActveRecord::Base 
    HAS_FIREPLACE = (1 << 0) 
    HAS_BASEMENT = (1 << 1) 
    HAS_GARAGE = (1 << 2) 

    ... 
end 

फिर कुछ मॉडल विशेषता flags कहा जाता है इस तरह सेट किया जाएगा:

flags |= HAS_FIREPLACE 
flags |= (HAS_BASEMENT | HAS_GARAGE) 

और परीक्षण किया इस तरह:

flags & HAS_FIREPLACE 
flags & (HAS_BASEMENT | HAS_GARAGE) 

जो आप तरीकों में सार सकता है। एक कार्यान्वयन के रूप में समय और स्थान में समय और स्थान में बहुत कुशल होना चाहिए

3

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

यदि आप प्रदर्शन के बारे में चिंता करने वाले नहीं हैं, तो मैं एक कार्यान्वयन का उपयोग करूंगा जहां प्रत्येक संपत्ति को एक चरित्र ("ए" = "गेराज", "बी" = "फायरप्लेस" आदि) द्वारा दर्शाया जाता है, और आप बस एक स्ट्रिंग बनाते हैं जो रिकॉर्ड के सभी झंडे का प्रतिनिधित्व करता है। एक बिटफील्ड पर इसका प्राथमिक लाभ यह है कि ए) मानव को डीबग करना आसान है, और बी) आपको अपने डेटा प्रकारों के आकार के बारे में चिंता करने की आवश्यकता नहीं है।

यदि प्रदर्शन एक चिंता है, तो आपको उन्हें प्रथम श्रेणी के क्षेत्रों में प्रचारित करने की आवश्यकता होगी।

2

आम तौर पर मैं सहमत हूं कि आपकी बेवकूफ धारणा सही है।

बूलियन फ़ील्ड की संख्या बढ़ रही है और बढ़ रही है (has_fusion_reactor?) रखें कि यदि आप भी झंडे

# house.rb 
class House 
    serialize :flags 
    … 
end 

# Setting flags 
@house.flags = [:fireplace, :pool, :doghouse] 
# Appending 
@house.flags << :sauna 
#Querying 
@house.flags.has_key? :porch 
#Searching 
House.where "flags LIKE ?", "pool" 
4

की एक सरणी serializing विचार कर सकते हैं यहाँ एक और समाधान है।

आप एक HouseAttributes मॉडल बनाने के लिए और एक दो तरह से has_and_belongs_to_many संघ

# house.rb 
class House 
    has_and_belongs_to_many :house_attributes 
end 

# house_attribute.rb 
class HouseAttribute 
    has_and_belongs_to_many :houses 
end 

की स्थापना की तो एक घर के लिए प्रत्येक विशेषता एक डेटाबेस प्रवेश किया जाएगा सकता है।

अपने डेटाबेस में अपनी जॉइन टेबल सेट अप करना न भूलें।

+2

+1 अतीत में मैंने इस दृष्टिकोण को चुना है, क्योंकि अधिक सुविधाओं को जोड़ने के लिए हमेशा आवश्यकता होती है (उस समय या बाद में) - यह केवल__olar_panels और has_futuretech के लिए पूछने से पहले ही समय की बात है। – edralph

1

मैं इस

की तरह कुछ के बारे में सोच रहा हूँ तुम एक हाउस टेबल

आपके पास एक और मास्टर तालिका विशेषताएं (जो, सुविधाओं की है 'चिमनी' की तरह कहा जाता है, '(घर की जानकारी के लिए) है तहखाने 'आदि ..)

और आप Houses_Features की तरह एक में शामिल होने की मेज और यह house_id और

feature_id कि जिस तरह से आप किसी दिए गए घर के लिए सुविधाओं प्रदान कर सकते हैं के द्वारा किया गया है है।

धन्यवाद और का संबंध

समीरा

5

मेरा सुझाव है the flag_shih_tzu gem डी: न कि क्या यह अपनी आवश्यकताओं के से मेल खाता है, लेकिन अभी इसके बारे में सोचो। यह आपको एक पूर्णांक कॉलम में कई बुलियन विशेषताओं को स्टोर करने में सहायता करता है। यह आपको प्रत्येक विशेषता के लिए स्कोप नामित करता है और सक्रिय रिकॉर्ड संबंधों के रूप में उन्हें एक साथ श्रृंखलाबद्ध करने का एक तरीका देता है।

संबंधित मुद्दे

 संबंधित मुद्दे