फायरबेस पर डेटा की संरचना का सबसे अच्छा तरीका क्या है?


111

मैं फायरबेस के लिए नया हूं और मैं जानना चाहता हूं कि इस पर डेटा को संरचित करने का सबसे अच्छा तरीका क्या है।

मेरे पास एक सरल उदाहरण है:

मेरी परियोजना पर आवेदक और अनुप्रयोग हैं। 1 आवेदक के पास कई आवेदन हो सकते हैं। मैं इस 2 वस्तुओं को फायरबेस पर कैसे संबंधित कर सकता हूं? क्या यह एक रिलेशनल डेटाबेस की तरह काम करता है? या डेटा डिजाइन के मामले में दृष्टिकोण पूरी तरह से अलग होना चाहिए?

जवाबों:


137

अद्यतन : अब संरचित डेटा पर एक डॉक्टर है । इसके अलावा, NoSQL डेटा संरचनाओं पर इस उत्कृष्ट पोस्ट को देखें ।

RDBMS के विपरीत, पदानुक्रमित डेटा के साथ मुख्य मुद्दा यह है कि यह घोंसले के डेटा को लुभा रहा है क्योंकि हम कर सकते हैं। आमतौर पर, आप बयानों और प्रश्नों की कमी के बावजूद डेटा को कुछ हद तक सामान्य करना चाहते हैं (जैसे आप SQL के साथ करेंगे)।

आप उन जगहों पर भी वंचित करना चाहते हैं जहां पढ़ने की क्षमता एक चिंता का विषय है। यह सभी बड़े पैमाने पर एप्लिकेशन (जैसे ट्विटर और फेसबुक) द्वारा उपयोग की जाने वाली तकनीक है और यद्यपि यह हमारे DRY सिद्धांतों के खिलाफ जाती है, यह आमतौर पर स्केलेबल ऐप्स की एक आवश्यक विशेषता है।

यहाँ सार यह है कि आप पठन को आसान बनाने के लिए लिखने के लिए कड़ी मेहनत करना चाहते हैं। तार्किक घटकों को अलग-अलग पढ़ा जाता है (जैसे कि चैट रूम के लिए, संदेशों को न रखें, कमरों के बारे में मेटा जानकारी और सभी सदस्यों की सूची एक ही स्थान पर, यदि आप बाद में समूहों को पुन: व्यवस्थित करना चाहते हैं)।

Firebase के वास्तविक समय डेटा और SQL वातावरण के बीच प्राथमिक अंतर डेटा क्वेरी कर रहा है। डेटा के वास्तविक समय की प्रकृति के कारण "इसका चयन करने के लिए कोई सरल तरीका नहीं है, जहां एक्स = वाई" है (यह लगातार बदलते, तेज, सामंजस्य, आदि है, जिसके कारण सिंक्रनाइज़ किए गए क्लाइंट को जांच में रखने के लिए एक सरल आंतरिक मॉडल की आवश्यकता होती है)

एक सरल उदाहरण शायद आपको मन की सही स्थिति में स्थापित कर देगा, इसलिए यहां दिया गया है:

/users/uid
/users/uid/email
/users/uid/messages
/users/uid/widgets

अब, चूंकि हम एक पदानुक्रमित संरचना में हैं, अगर मैं उपयोगकर्ताओं के ईमेल पते को पुन: क्रमबद्ध करना चाहता हूं, तो मैं कुछ इस तरह करता हूं:

// I could also use on('child_added') here to great success
// but this is simpler for an example
firebaseRef.child('users').once('value')
.then(userPathSnapshot => {
   userPathSnapshot.forEach(
      userSnap => console.log('email', userSnap.val().email)
   );
})
.catch(e => console.error(e));

इस दृष्टिकोण के साथ समस्या यह है कि मैंने ग्राहक को केवल सभी उपयोगकर्ताओं को डाउनलोड करने के लिए मजबूर किया है messagesऔर widgetsभी। कोई बड़ी बात नहीं अगर उन चीजों में से कोई हजारों की संख्या में। लेकिन 10k उपयोगकर्ताओं के लिए एक बड़ा सौदा प्रत्येक 5k संदेशों के ऊपर की ओर है।

तो अब एक पदानुक्रमित, वास्तविक समय संरचना के लिए इष्टतम रणनीति अधिक स्पष्ट हो जाती है:

/user_meta/uid/email
/messages/uid/...
/widgets/uid/...

एक अतिरिक्त उपकरण जो इस वातावरण में अत्यंत उपयोगी है, सूचक हैं। कुछ विशेषताओं वाले उपयोगकर्ताओं का एक इंडेक्स बनाकर, मैं केवल एसक्यूएल क्वेरी को केवल इंडेक्स को पुनरावृत्त करके अनुकरण कर सकता हूं:

/users_with_gmail_accounts/uid/email

अब अगर मुझे gmail उपयोगकर्ताओं के लिए संदेश प्राप्त करना, कहना, मैं कुछ इस तरह से कर सकता हूं:

var ref = firebase.database().ref('users_with_gmail_accounts');
ref.once('value').then(idx_snap => {
   idx_snap.forEach(idx_entry => {
       let msg = idx_entry.name() + ' has a new message!';
       firebase.database().ref('messages').child(idx_entry.name())
          .on(
             'child_added', 
             ss => console.log(msg, ss.key);
          );
   });
})
.catch(e => console.error(e));

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


इस अंतर्दृष्टि के लिए धन्यवाद Kato!
हॉपर

2
उतने समय के लिए। Firebase के v2 रिलीज के विचारों में उस प्रक्रिया को स्वचालित करने के लिए कुछ महान क्षमताएं होंगी।
काटो

जागरूक हूं कि मैं यहां एक पुरानी टिप्पणी के धागे को फिर से जीवित कर रहा हूं, लेकिन मैं एक और अप-टू-डेट समाधान खोजने के लिए संघर्ष कर रहा हूं। क्या यह अभी भी सबसे अच्छा तरीका है? अर्थात सभी उपयोगकर्ता प्राप्त कर रहे हैं_with_gmail_accounts और फिर एक forEach चलाना?
उल्लू

48

फायरबेस एक रिलेशनल डेटाबेस की तरह नहीं है। यदि आप इसे किसी भी चीज़ से तुलना करना चाहते हैं, तो मैं इसकी तुलना एक पदानुक्रमित डेटाबेस से करूँगा।

अनंत ने हाल ही में आपके डेटा को निरूपित करने के बारे में फायरबेस ब्लॉग पर एक शानदार पोस्ट लिखा है: https://www.firebase.com/blog/2013-04-12-denormalizing-is-normal.html

मैं वास्तव में प्रत्येक आवेदक के बच्चे के रूप में प्रत्येक आवेदन की "आईडी" रखने का सुझाव दूंगा।


धन्यवाद फ्रैंक! यह वास्तव में मददगार है। ठीक वही जो मेरे द्वारा खोजा जा रहा था !
हॉपर

4

आपका परिदृश्य संबंधपरक दुनिया में एक से कई दिखता है, आपके उदाहरण के अनुसार एक आवेदक के पास कई एप्लिकेशन हैं। अगर हम फायरबॉस्स nosql तरीके से आते हैं तो यह नीचे जैसा दिखता है। यह बिना किसी प्रदर्शन के मुद्दों के पैमाने पर होना चाहिए। इसीलिए हमें नीचे दिए गए अनुसार विकेंद्रीकरण की आवश्यकता है।

applicants:{
applicant1:{
    .
    .
    applications:{
        application1:true,
        application3:true
    }
},
applicant2:{
    .
    .
    applications:{
        application2:true,
        application4:true
    }
}}

applications:{
application1:{
    .
    .
},
application2:{
    .
    .
},
application3:{
    .
    .
},
application4:{
    .
    .
}}

अच्छा है, लेकिन मेरे पास फॉलो-ऑन है, हम स्विफ्ट से या कहीं भी फायरबेस एसडीके का उपयोग करके इस संरचना को कैसे बनाते हैं? हम यह भी कैसे मान्य कर सकते हैं कि एप्लिकेशन नोड में जोड़ा गया नया डेटा वास्तव में मौजूद है। फायरबेस सत्यापन नियमों का उपयोग करके एप्लिकेशन सूची में?
टॉमी सी।

@prateep, अच्छा उदाहरण। लेकिन यहाँ मुद्दा यह है कि जब मैं पथ अनुप्रयोगों / Application1 को हटाता हूं, जहां कुछ आवेदकों के लिए Application1 बच्चा है। यदि मैं पथ आवेदकों / application1 तक पहुंचने का प्रयास करता हूं जो वहां नहीं है। इसलिए आपको Application1: {applicants: {applicant1: true} ...} दोनों जगहों पर अनुक्रमित अपडेट करने की आवश्यकता है, इसलिए अब जब मैं applicantion1 को हटाता हूं तो मुझे यह देखना होगा कि यह बाल आवेदक है और आवेदन के लिए आवेदकों के बच्चे के नोड को अपडेट करें। :)
सतीश सोजित्रा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.