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

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

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

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

सभी फायरबेस रीयलटाइम डेटाबेस डेटा 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 प्रकारों के अनुरूप होते हैं।

डेटा संरचना के लिए सर्वोत्तम अभ्यास

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

क्योंकि फायरबेस रीयलटाइम डेटाबेस 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 की सदस्यताएँ जल्दी और कुशलता से प्राप्त करने की अनुमति देता है, तब भी जब उपयोगकर्ताओं या समूहों की सूची लाखों में हो या जब रीयलटाइम डेटाबेस सुरक्षा नियम कुछ रिकॉर्ड्स तक पहुंच को रोकते हों।

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

अगले कदम