C++ के लिए, Firebase रीयल टाइम डेटाबेस की मदद से डेटा स्ट्रक्चर करना

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

इस गाइड में, डेटा आर्किटेक्चर से जुड़े कुछ अहम कॉन्सेप्ट और JSON डेटा को स्ट्रक्चर करने के सबसे सही तरीकों के बारे में बताया गया है Firebase Realtime Database.

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

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

सारा डेटा, JSON ऑब्जेक्ट के तौर पर सेव किया जाता है.Firebase Realtime Database डेटाबेस को क्लाउड पर होस्ट किए गए JSON ट्री के तौर पर देखा जा सकता है. SQL डेटाबेस के उलट, इसमें टेबल या रिकॉर्ड नहीं होते. 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 को ऐडा की प्रोफ़ाइल में शामिल किया गया है. इसलिए, ऐडा को ग्रुप से हटाने के लिए, उसे दो जगहों पर अपडेट करना होगा.

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

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

अगले चरण