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

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

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

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

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

अगर आपने खुद की कुंजियां बनाई हैं, तो वे UTF-8 कोड में बदली गई होनी चाहिए. ये ज़्यादा से ज़्यादा 768 बाइट की हो सकती हैं. साथ ही, इनमें ., $, #, [, ], / या ASCII कंट्रोल वाले वर्ण 0-31 या 127 नहीं होने चाहिए. आप मानों में भी ASCII नियंत्रण वर्णों का इस्तेमाल नहीं कर सकते.

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

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

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

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

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

Firebase रीयलटाइम डेटाबेस, 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
      }
    },
    ...
  }
}

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

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

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

अगले चरण