शुरू करने से पहले
Realtime Database का इस्तेमाल करने से पहले, आपको ये काम करने होंगे:
अपना Unity प्रोजेक्ट रजिस्टर करें और उसे Firebase का इस्तेमाल करने के लिए कॉन्फ़िगर करें.
अगर आपका Unity प्रोजेक्ट पहले से ही Firebase का इस्तेमाल करता है, तो इसका मतलब है कि वह Firebase के लिए पहले से ही रजिस्टर और कॉन्फ़िगर है.
अगर आपके पास कोई Unity प्रोजेक्ट नहीं है, तो सैंपल ऐप्लिकेशन डाउनलोड किया जा सकता है.
अपने Unity प्रोजेक्ट में Firebase Unity SDK टूल (खास तौर पर,
FirebaseDatabase.unitypackage
) जोड़ें.
ध्यान दें कि अपने Unity प्रोजेक्ट में Firebase जोड़ने के लिए, Firebase कंसोल और अपने खुले हुए Unity प्रोजेक्ट, दोनों में टास्क शामिल होते हैं. उदाहरण के लिए, कंसोल से Firebase कॉन्फ़िगरेशन फ़ाइलें डाउनलोड करके, उन्हें अपने Unity प्रोजेक्ट में ले जाना.
डेटा को व्यवस्थित करना
इस गाइड में, डेटा आर्किटेक्चर के कुछ मुख्य कॉन्सेप्ट और Firebase Realtime Database में JSON डेटा को स्ट्रक्चर करने के सबसे सही तरीकों के बारे में बताया गया है.
एक सही तरीके से स्ट्रक्चर किया गया डेटाबेस बनाने के लिए, काफ़ी पहले से सोच-विचार करने की ज़रूरत होती है. सबसे ज़रूरी बात यह है कि आपको यह तय करना होगा कि डेटा को कैसे सेव किया जाएगा और बाद में उसे कैसे वापस पाया जाएगा, ताकि इस प्रोसेस को आसान बनाया जा सके.
डेटा को कैसे स्ट्रक्चर किया जाता है: यह एक JSON ट्री है
Firebase Realtime Database का सारा डेटा, 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 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 } }, ... } }
आप देख सकते हैं कि यह Ada के रिकॉर्ड और ग्रुप, दोनों में संबंध को सेव करके कुछ डेटा का डुप्लीकेट बनाता है. अब alovelace
को ग्रुप के तहत इंडेक्स किया गया है और techpioneers
को ऐडा की प्रोफ़ाइल में शामिल किया गया है. इसलिए, ग्रुप से Ada को मिटाने के लिए, उसे दो जगहों पर अपडेट करना होगा.
यह दोतरफ़ा संबंधों के लिए ज़रूरी है. इसकी मदद से, Ada की सदस्यताओं को तेज़ी से और आसानी से फ़ेच किया जा सकता है. भले ही, उपयोगकर्ताओं या ग्रुप की संख्या लाखों में हो या Realtime Database सुरक्षा नियमों की वजह से कुछ रिकॉर्ड ऐक्सेस न किए जा सकें.
इस तरीके में, आईडी को कुंजियों के तौर पर लिस्ट करके और वैल्यू को 'सही' पर सेट करके, डेटा को उलट दिया जाता है. इससे, किसी कुंजी की जांच करना उतना ही आसान हो जाता है जितना कि /users/$uid/groups/$group_id
को पढ़ना और यह देखना कि वह null
है या नहीं. इंडेक्स, डेटा को क्वेरी करने या स्कैन करने की तुलना में तेज़ और ज़्यादा असरदार होता है.