अपने डेटाबेस का स्ट्रक्चर तैयार करें

इस गाइड में, डेटा आर्किटेक्चर के कुछ मुख्य सिद्धांतों के बारे में बताया गया है. साथ ही, Firebase Realtime Database में JSON डेटा को स्ट्रक्चर करने के सबसे सही तरीकों के बारे में बताया गया है.

सही तरीके से स्ट्रक्चर्ड डेटाबेस बनाने के लिए, पहले से ही काफ़ी सोच-विचार करना पड़ता है. सबसे ज़रूरी बात यह है कि आपको यह प्लान करना होगा कि डेटा को कैसे सेव किया जाएगा और बाद में उसे कैसे वापस लाया जाएगा, ताकि यह प्रोसेस ज़्यादा से ज़्यादा आसान हो सके.

डेटा को कैसे स्ट्रक्चर किया जाता है: यह एक JSON ट्री है

Firebase Realtime Database का सारा डेटा, JSON ऑब्जेक्ट के तौर पर सेव किया जाता है. डेटाबेस को क्लाउड पर होस्ट किए गए JSON ट्री के तौर पर समझा जा सकता है. एसक्यूएल डेटाबेस के उलट, इसमें कोई टेबल या रिकॉर्ड नहीं होता. JSON ट्री में डेटा जोड़ने पर, वह मौजूदा JSON स्ट्रक्चर में एक नोड बन जाता है. साथ ही, उससे एक कुंजी जुड़ जाती है. आपके पास अपनी कुंजियां देने का विकल्प होता है. जैसे, यूज़र आईडी या सिमैंटिक नाम. इसके अलावा, push() का इस्तेमाल करके भी कुंजियां दी जा सकती हैं.

उदाहरण के लिए, मान लें कि कोई चैट ऐप्लिकेशन है, जो उपयोगकर्ताओं को बुनियादी प्रोफ़ाइल और संपर्क सूची सेव करने की अनुमति देता है. आम तौर पर, उपयोगकर्ता की प्रोफ़ाइल इस पाथ पर मौजूद होती है: /users/$uid. उपयोगकर्ता alovelace के पास डेटाबेस की कोई ऐसी एंट्री हो सकती है जो कुछ इस तरह दिखती हो:

{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      "contacts": { "ghopper": true },
    },
    "ghopper": { "..." },
    "eclarke": { "..." }
  }
}

डेटाबेस में JSON ट्री का इस्तेमाल किया जाता है. हालांकि, डेटाबेस में सेव किए गए डेटा को कुछ नेटिव टाइप के तौर पर दिखाया जा सकता है. ये टाइप, उपलब्ध JSON टाइप से मेल खाते हैं. इससे आपको ऐसा कोड लिखने में मदद मिलती है जिसे आसानी से मैनेज किया जा सके.

डेटा स्ट्रक्चर के लिए सबसे सही तरीके

डेटा को नेस्ट करने से बचें

Firebase Realtime Database में डेटा को 32 लेवल तक नेस्ट किया जा सकता है. इसलिए, आपको लग सकता है कि यह डिफ़ॉल्ट स्ट्रक्चर होना चाहिए. हालांकि, अपने डेटाबेस में किसी जगह से डेटा फ़ेच करने पर, आपको उसके सभी चाइल्ड नोड भी मिलते हैं. इसके अलावा, जब किसी व्यक्ति को अपने डेटाबेस के किसी नोड में डेटा को पढ़ने या उसमें बदलाव करने का ऐक्सेस दिया जाता है, तो उसे उस नोड में मौजूद सभी डेटा का ऐक्सेस भी मिल जाता है. इसलिए, असल में, अपने डेटा स्ट्रक्चर को जितना हो सके उतना फ़्लैट रखना सबसे अच्छा है.

नेस्ट किया गया डेटा क्यों खराब होता है, इसका उदाहरण देखने के लिए, यहां दिया गया मल्टी-नेस्टेड स्ट्रक्चर देखें:

{
  // This is a poorly nested data architecture, because iterating the children
  // of the "chats" node to get a list of conversation titles requires
  // potentially downloading hundreds of megabytes of messages
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "messages": {
        "m1": { "sender": "ghopper", "message": "Relay malfunction found. Cause: moth." },
        "m2": { ... },
        // a very long list of messages
      }
    },
    "two": { "..." }
  }
}

इस नेस्ट किए गए डिज़ाइन की वजह से, डेटा को बार-बार दोहराने में समस्या आती है. उदाहरण के लिए, चैट बातचीत के टाइटल की सूची बनाने के लिए, क्लाइंट को पूरा chats ट्री डाउनलोड करना होगा. इसमें सभी सदस्य और मैसेज शामिल हैं.

डेटा स्ट्रक्चर को फ़्लैट करना

अगर डेटा को अलग-अलग पाथ में बांटा जाता है, तो इसे डिनॉर्मलाइज़ेशन भी कहा जाता है. इसे ज़रूरत के हिसाब से, अलग-अलग कॉल में आसानी से डाउनलोड किया जा सकता है. इस फ़्लैट स्ट्रक्चर पर ध्यान दें:

{
  // Chats contains only meta info about each conversation
  // stored under the chats's unique ID
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
      "timestamp": 1459361875666
    },
    "two": { "..." },
    "three": { "..." }
  },

  // Conversation members are easily accessible
  // and stored by chat conversation ID
  "members": {
    // we'll talk about indices like this below
    "one": {
      "ghopper": true,
      "alovelace": true,
      "eclarke": true
    },
    "two": { "..." },
    "three": { "..." }
  },

  // Messages are separate from data we may want to iterate quickly
  // but still easily paginated and queried, and organized by chat
  // conversation ID
  "messages": {
    "one": {
      "m1": {
        "name": "eclarke",
        "message": "The relay seems to be malfunctioning.",
        "timestamp": 1459361875337
      },
      "m2": { "..." },
      "m3": { "..." }
    },
    "two": { "..." },
    "three": { "..." }
  }
}

अब हर बातचीत के लिए सिर्फ़ कुछ बाइट डाउनलोड करके, रूम की सूची को बार-बार देखा जा सकता है. इससे यूज़र इंटरफ़ेस (यूआई) में रूम की सूची बनाने या दिखाने के लिए, मेटाडेटा को तेज़ी से फ़ेच किया जा सकता है. मैसेज अलग से फ़ेच किए जा सकते हैं और उनके आते ही उन्हें दिखाया जा सकता है. इससे यूज़र इंटरफ़ेस (यूआई) तेज़ी से काम करता है और रिस्पॉन्सिव बना रहता है.

स्केल करने वाला डेटा बनाना

ऐप्लिकेशन बनाते समय, अक्सर किसी सूची का सबसेट डाउनलोड करना बेहतर होता है. ऐसा आम तौर पर तब होता है, जब सूची में हज़ारों रिकॉर्ड हों. जब यह रिलेशनशिप स्टैटिक और एकतरफ़ा हो, तो चाइल्ड ऑब्जेक्ट को पैरंट ऑब्जेक्ट के अंदर नेस्ट किया जा सकता है.

कभी-कभी, यह संबंध ज़्यादा डाइनैमिक होता है या इस डेटा को डीनॉर्मलाइज़ करना ज़रूरी हो सकता है. कई बार, डेटा के सबसेट को वापस पाने के लिए क्वेरी का इस्तेमाल करके, डेटा को डीनॉर्मलाइज़ किया जा सकता है. इसके बारे में डेटा वापस पाना में बताया गया है.

हालांकि, ऐसा हो सकता है कि यह भी काफ़ी न हो. उदाहरण के लिए, उपयोगकर्ताओं और ग्रुप के बीच दोतरफ़ा संबंध पर विचार करें. उपयोगकर्ता किसी ग्रुप का हिस्सा हो सकते हैं. साथ ही, ग्रुप में उपयोगकर्ताओं की सूची होती है. जब यह तय करने का समय आता है कि कोई उपयोगकर्ता किन ग्रुप का हिस्सा है, तो चीज़ें मुश्किल हो जाती हैं.

इसके लिए, एक ऐसा तरीका चाहिए जिससे उन ग्रुप की सूची बनाई जा सके जिनका कोई उपयोगकर्ता हिस्सा है. साथ ही, सिर्फ़ उन ग्रुप का डेटा फ़ेच किया जा सके. ग्रुप का इंडेक्स, इसमें काफ़ी मदद कर सकता है:

// An index to track Ada's memberships
{
  "users": {
    "alovelace": {
      "name": "Ada Lovelace",
      // Index Ada's groups in her profile
      "groups": {
         // the value here doesn't matter, just that the key exists
         "techpioneers": true,
         "womentechmakers": true
      }
    },
    // ...
  },
  "groups": {
    "techpioneers": {
      "name": "Historical Tech Pioneers",
      "members": {
        "alovelace": true,
        "ghopper": true,
        "eclarke": true
      }
    },
    // ...
  }
}

आपको दिख सकता है कि इससे कुछ डेटा डुप्लीकेट हो जाता है. ऐसा इसलिए होता है, क्योंकि संबंध की जानकारी को अदा के रिकॉर्ड और ग्रुप, दोनों में सेव किया जाता है. अब alovelace को एक ग्रुप में इंडेक्स किया गया है. साथ ही, techpioneers को अदा की प्रोफ़ाइल में शामिल किया गया है. इसलिए, Ada को ग्रुप से हटाने के लिए, आपको दो जगहों पर अपडेट करना होगा.

यह दो-तरफ़ा संबंधों के लिए ज़रूरी है. इससे आपको Ada की सदस्यताओं को तेज़ी से और बेहतर तरीके से फ़ेच करने में मदद मिलती है. भले ही, उपयोगकर्ताओं या ग्रुप की सूची लाखों में हो या Realtime Database के सुरक्षा नियम कुछ रिकॉर्ड को ऐक्सेस करने से रोकते हों.

इस तरीके में, आईडी को कुंजियों के तौर पर लिस्ट करके और वैल्यू को true पर सेट करके, डेटा को इनवर्ट किया जाता है. इससे किसी कुंजी की जांच करना, /users/$uid/groups/$group_id को पढ़ने और यह देखने जितना आसान हो जाता है कि वह null है या नहीं. इंडेक्स, डेटा को क्वेरी या स्कैन करने की तुलना में ज़्यादा तेज़ और बेहतर होता है.

अगले चरण