शुरू करें
अगर आपने अब तक अपना ऐप्लिकेशन और डेटाबेस का ऐक्सेस सेट अप नहीं किया है, तो पहले Get Started
गाइड देखें.
DatabaseReference पाना
डेटाबेस में डेटा लिखने के लिए, आपको DatabaseReference
के इंस्टेंस की ज़रूरत होगी:
// Get the root reference location of the database. firebase::database::DatabaseReference dbref = database->GetReference();
डेटा सेव करना
Firebase Realtime Database में डेटा लिखने के चार तरीके हैं:
तरीका | सामान्य तौर पर क्वेरी की सूची का इस्तेमाल इस तरह किया जाता है |
---|---|
SetValue() |
किसी तय किए गए पाथ पर डेटा लिखें या बदलें. जैसे, users/<user-id>/<username> . |
PushChild() |
डेटा की सूची में जोड़ें. जब भी Push() को कॉल किया जाता है, Firebase एक यूनीक कुंजी जनरेट करता है. इसका इस्तेमाल यूनीक आइडेंटिफ़ायर के तौर पर भी किया जा सकता है. जैसे, user-scores/<user-id>/<unique-score-id> . |
UpdateChildren() |
पूरे डेटा को बदले बिना, तय किए गए पाथ के लिए कुछ कुंजियां अपडेट करें. |
RunTransaction() |
ऐसे जटिल डेटा को अपडेट करें जो एक साथ हो रहे अपडेट की वजह से खराब हो सकता है. |
किसी रेफ़रंस पर डेटा लिखना, अपडेट करना या मिटाना
लिखने की बुनियादी कार्रवाइयां
लिखने से जुड़ी बुनियादी कार्रवाइयों के लिए, SetValue()
का इस्तेमाल करके डेटा को किसी तय रेफ़रंस में सेव किया जा सकता है. इससे उस पाथ पर मौजूद मौजूदा डेटा बदल जाता है. इस तरीके का इस्तेमाल करके, JSON में स्वीकार किए गए टाइप को Variant टाइप के ज़रिए पास किया जा सकता है. Variant टाइप में ये सुविधाएं होती हैं:
- शून्य (इससे डेटा मिट जाता है)
- पूर्णांक (64-बिट)
- डबल प्रेसिज़न फ़्लोटिंग पॉइंट नंबर
- बूलियन
- स्ट्रिंग
- वैरिएंट के वेक्टर
- स्ट्रिंग से वैरिएंट के मैप
SetValue()
का इस तरह इस्तेमाल करने से, तय की गई जगह पर मौजूद डेटा मिट जाता है. इसमें चाइल्ड नोड भी शामिल हैं. हालांकि, पूरे ऑब्जेक्ट को फिर से लिखे बिना भी किसी बच्चे की जानकारी अपडेट की जा सकती है. अगर आपको उपयोगकर्ताओं को अपनी प्रोफ़ाइल अपडेट करने की अनुमति देनी है, तो उपयोगकर्ता नाम को इस तरह अपडेट करें:
dbref.Child("users").Child(userId).Child("username").SetValue(name);
डेटा की सूची में जोड़ना
एक से ज़्यादा उपयोगकर्ताओं वाले ऐप्लिकेशन में, किसी सूची में डेटा जोड़ने के लिए PushChild()
तरीके का इस्तेमाल करें.
PushChild()
तरीके से, हर बार एक यूनीक कुंजी जनरेट होती है. ऐसा तब होता है, जब किसी Firebase रेफ़रंस में कोई नया चाइल्ड जोड़ा जाता है. सूची में मौजूद हर नए एलिमेंट के लिए, अपने-आप जनरेट होने वाली इन कुंजियों का इस्तेमाल करके, कई क्लाइंट एक ही समय में एक ही जगह पर बच्चों को जोड़ सकते हैं. इससे लिखने से जुड़ी समस्याएं नहीं होती हैं. PushChild()
से जनरेट की गई यूनीक कुंजी, टाइमस्टैंप पर आधारित होती है. इसलिए, सूची के आइटम अपने-आप समय के हिसाब से क्रम में लग जाते हैं.
PushChild()
तरीके से मिले नए डेटा के रेफ़रंस का इस्तेमाल करके, बच्चे के लिए अपने-आप जनरेट हुई कुंजी की वैल्यू पाई जा सकती है. इसके अलावा, बच्चे के लिए डेटा सेट किया जा सकता है.
PushChild()
रेफ़रंस पर GetKey()
को कॉल करने पर, अपने-आप जनरेट होने वाली कुंजी की वैल्यू मिलती है.
चुनिंदा फ़ील्ड अपडेट करना
अगर आपको किसी नोड के कुछ बच्चों को एक साथ लिखना है और अन्य चाइल्ड नोड को नहीं बदलना है, तो UpdateChildren()
तरीके का इस्तेमाल करें.
UpdateChildren()
को कॉल करते समय, कुंजी के लिए पाथ तय करके, निचले लेवल की चाइल्ड वैल्यू अपडेट की जा सकती हैं. अगर डेटा को बेहतर तरीके से स्केल करने के लिए, उसे एक से ज़्यादा जगहों पर सेव किया जाता है, तो डेटा फ़ैन-आउट का इस्तेमाल करके, उस डेटा के सभी इंस्टेंस को अपडेट किया जा सकता है. उदाहरण के लिए, किसी गेम में LeaderboardEntry
क्लास इस तरह हो सकती है:
class LeaderboardEntry { std::string uid; int score = 0; public: LeaderboardEntry() { } LeaderboardEntry(std::string uid, int score) { this->uid = uid; this->score = score; } std::map<std::string, Object> ToMap() { std::map<string, Variant> result = new std::map<string, Variant>(); result["uid"] = Variant(uid); result["score"] = Variant(score); return result; } }
LeaderboardEntry
बनाने और उसे एक साथ हाल ही के स्कोर फ़ीड और उपयोगकर्ता की स्कोर सूची में अपडेट करने के लिए, गेम इस कोड का इस्तेमाल करता है:
void WriteNewScore(std::string userId, int score) { // Create new entry at /user-scores/$userid/$scoreid and at // /leaderboard/$scoreid simultaneously std::string key = dbref.Child("scores").PushChild().GetKey(); LeaderBoardEntry entry = new LeaderBoardEntry(userId, score); std::map<std::string, Variant> entryValues = entry.ToMap(); std::map<string, Variant> childUpdates = new std::map<string, Variant>(); childUpdates["/scores/" + key] = entryValues; childUpdates["/user-scores/" + userId + "/" + key] = entryValues; dbref.UpdateChildren(childUpdates); }
इस उदाहरण में, PushChild()
का इस्तेमाल करके, /scores/$key
पर सभी उपयोगकर्ताओं के लिए एंट्री वाले नोड में एक एंट्री बनाई गई है. साथ ही, key()
की मदद से कुंजी वापस पाई गई है. इसके बाद, इस कुंजी का इस्तेमाल करके, उपयोगकर्ता के स्कोर में दूसरी एंट्री की जा सकती है. यह एंट्री /user-scores/$userid/$key
पर की जाती है.
इन पाथ का इस्तेमाल करके, JSON ट्री में मौजूद कई जगहों की जानकारी को एक साथ अपडेट किया जा सकता है. इसके लिए, UpdateChildren()
को सिर्फ़ एक बार कॉल करना होगा. उदाहरण के लिए, इस उदाहरण में दिखाया गया है कि कैसे दोनों जगहों के लिए नई एंट्री बनाई जाती है. इस तरह से एक साथ किए गए अपडेट ऐटॉमिक होते हैं: या तो सभी अपडेट पूरे होते हैं या सभी अपडेट पूरे नहीं होते हैं.
डेटा मिटाना
डेटा मिटाने का सबसे आसान तरीका यह है कि उस डेटा के रेफ़रंस पर RemoveValue()
कॉल करें.
SetValue()
या UpdateChildren()
जैसे किसी अन्य राइट ऑपरेशन के लिए, वैल्यू के तौर पर null
Variant
तय करके भी मिटाया जा सकता है. इस तकनीक का इस्तेमाल UpdateChildren()
के साथ करके, एक ही एपीआई कॉल में कई बच्चों के खाते मिटाए जा सकते हैं.
जानें कि आपका डेटा कब सेव किया जाता है.
यह जानने के लिए कि आपका डेटा Firebase Realtime Database सर्वर पर कब सबमिट किया गया, Future के नतीजे में 'सफल' स्टेटस देखें.
डेटा को लेन-देन के तौर पर सेव करना
अगर आपको ऐसे डेटा के साथ काम करना है जिसमें एक साथ कई बदलाव किए जा सकते हैं, तो लेन-देन के ऑपरेशन का इस्तेमाल किया जा सकता है. जैसे, इंक्रीमेंटल काउंटर.
इस ऑपरेशन को DoTransaction
फ़ंक्शन दिया जाता है. यह अपडेट फ़ंक्शन, डेटा की मौजूदा स्थिति को आर्ग्युमेंट के तौर पर लेता है. साथ ही, नई स्थिति दिखाता है. अगर कोई दूसरा क्लाइंट, आपकी नई वैल्यू के सेव होने से पहले ही लोकेशन में बदलाव करता है, तो अपडेट फ़ंक्शन को नई वैल्यू के साथ फिर से कॉल किया जाता है. इसके बाद, बदलाव करने की कोशिश फिर से की जाती है.
उदाहरण के लिए, किसी गेम में उपयोगकर्ताओं को लीडरबोर्ड को अपडेट करने की अनुमति दी जा सकती है. इसमें सबसे ज़्यादा स्कोर वाले पाँच स्कोर शामिल किए जा सकते हैं:
void AddScoreToLeaders(std::string email, long score, DatabaseReference leaderBoardRef) { leaderBoardRef.RunTransaction([](firebase::database::MutableData* mutableData) { if (mutableData.children_count() >= MaxScores) { long minScore = LONG_MAX; MutableData *minVal = null; std::vector<MutableData> children = mutableData.children(); std::vector<MutableData>::iterator it; for (it = children.begin(); it != children.end(); ++it) { if (!it->value().is_map()) continue; long childScore = (long)it->Child("score").value().int64_value(); if (childScore < minScore) { minScore = childScore; minVal = &*it; } } if (minScore > score) { // The new score is lower than the existing 5 scores, abort. return kTransactionResultAbort; } // Remove the lowest score. children.Remove(minVal); } // Add the new high score. std::map<std::string, Variant> newScoreMap = new std::map<std::string, Variant>(); newScoreMap["score"] = score; newScoreMap["email"] = email; children.Add(newScoreMap); mutableData->set_value(children); return kTransactionResultSuccess; }); }
लेन-देन का इस्तेमाल करने से, एक ही समय पर कई उपयोगकर्ताओं के स्कोर रिकॉर्ड करने या क्लाइंट के पास पुराना डेटा होने पर, लीडरबोर्ड में गलत जानकारी नहीं दिखती. अगर लेन-देन अस्वीकार कर दिया जाता है, तो सर्वर क्लाइंट को मौजूदा वैल्यू दिखाता है. इसके बाद, क्लाइंट अपडेट की गई वैल्यू के साथ लेन-देन को फिर से शुरू करता है. यह प्रोसेस तब तक दोहराई जाती है, जब तक लेन-देन स्वीकार नहीं हो जाता या बहुत ज़्यादा कोशिशें नहीं हो जातीं.
ऑफ़लाइन डेटा सेव करने की अनुमति दें
अगर किसी क्लाइंट का नेटवर्क कनेक्शन बंद हो जाता है, तो आपका ऐप्लिकेशन ठीक से काम करता रहेगा.
Firebase डेटाबेस से कनेक्ट किया गया हर क्लाइंट, ऐक्टिव डेटा के अपने इंटरनल वर्शन को बनाए रखता है. डेटा को सबसे पहले इस लोकल वर्शन में लिखा जाता है. इसके बाद, Firebase क्लाइंट उस डेटा को रिमोट डेटाबेस सर्वर और अन्य क्लाइंट के साथ "बेस्ट-एफ़र्ट" के आधार पर सिंक करता है.
इस वजह से, डेटाबेस में कुछ भी लिखने पर, लोकल इवेंट तुरंत ट्रिगर हो जाते हैं. ऐसा सर्वर पर कोई भी डेटा लिखे जाने से पहले होता है. इसका मतलब है कि नेटवर्क की स्पीड कम होने या कनेक्टिविटी न होने पर भी, आपका ऐप्लिकेशन काम करता रहेगा.
कनेक्टिविटी फिर से चालू होने पर, आपके ऐप्लिकेशन को इवेंट का सही सेट मिलता है. इससे क्लाइंट, सर्वर की मौजूदा स्थिति के साथ सिंक हो जाता है. इसके लिए, आपको कोई कस्टम कोड लिखने की ज़रूरत नहीं होती.