शुरू करें
अगर आपने अब तक अपना ऐप्लिकेशन सेट अप नहीं किया है और डेटाबेस का ऐक्सेस नहीं लिया है, तो सबसे पहले 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()` को कॉल करने पर
Push(), Firebase एक यूनीक कुंजी जनरेट करता है. इसका इस्तेमाल यूनीक आइडेंटिफ़ायर के तौर पर भी किया जा सकता है
. जैसे, user-scores/<user-id>/<unique-score-id>. |
UpdateChildren() |
पूरा डेटा बदले बिना, तय किए गए पाथ के लिए कुछ कुंजियां अपडेट करना. |
RunTransaction() |
जटिल डेटा अपडेट करना. ऐसा डेटा, एक साथ हो रहे अपडेट की वजह से खराब हो सकता है. |
रेफ़रंस में डेटा सेव करना, अपडेट करना या मिटाना
डेटा सेव करने की बुनियादी कार्रवाइयां
डेटा सेव करने की बुनियादी कार्रवाइयों के लिए, SetValue() का इस्तेमाल करके, तय किए गए रेफ़रंस में डेटा सेव किया जा सकता है. इससे उस पाथ पर मौजूद मौजूदा डेटा बदल जाता है. इस तरीके का इस्तेमाल करके, JSON से स्वीकार किए जाने वाले टाइप को वैरिएंट टाइप के ज़रिए पास किया जा सकता है. यह टाइप इन चीज़ों के साथ काम करता है:
- Null (इससे डेटा मिट जाता है)
- इंटिजर (64-बिट)
- डबल प्रिसिशन फ़्लोटिंग पॉइंट नंबर
- बूलियन
- स्ट्रिंग
- वैरिएंट के वेक्टर
- वैरिएंट के लिए स्ट्रिंग के मैप
SetValue() का इस्तेमाल करने पर, तय की गई जगह पर मौजूद डेटा ओवरराइट हो जाता है. इसमें चाइल्ड नोड भी शामिल होते हैं. हालांकि, पूरे ऑब्जेक्ट को फिर से लिखे बिना भी चाइल्ड को अपडेट किया जा सकता है. अगर आपको उपयोगकर्ताओं को अपनी प्रोफ़ाइल अपडेट करने की अनुमति देनी है, तो उपयोगकर्ता नाम को इस तरह अपडेट किया जा सकता है:
dbref.Child("users").Child(userId).Child("username").SetValue(name);
डेटा की सूची में डेटा जोड़ना
मल्टी-यूज़र ऐप्लिकेशन में, डेटा को सूची में जोड़ने के लिए PushChild() तरीके का इस्तेमाल करें.
तय किए गए Firebase रेफ़रंस में नया चाइल्ड जोड़ने पर, PushChild() तरीका एक यूनीक कुंजी जनरेट करता है. सूची में मौजूद हर नए एलिमेंट के लिए, अपने-आप जनरेट होने वाली इन कुंजियों का इस्तेमाल करके, कई क्लाइंट एक ही जगह पर एक साथ चाइल्ड जोड़ सकते हैं. इससे डेटा सेव करने में कोई समस्या नहीं आती. 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); }
इस उदाहरण में, /scores/$key पर सभी उपयोगकर्ताओं के लिए एंट्री वाले नोड में एंट्री बनाने के लिए, PushChild() का इस्तेमाल किया गया है. साथ ही, key() की मदद से कुंजी को एक साथ वापस पाया गया है. इसके बाद, कुंजी का इस्तेमाल करके, /user-scores/$userid/$key पर उपयोगकर्ता के स्कोर में दूसरी एंट्री बनाई जा सकती है.
इन पाथ का इस्तेमाल करके, JSON ट्री में कई जगहों पर एक साथ अपडेट किए जा सकते हैं. इसके लिए, UpdateChildren() को सिर्फ़ एक बार कॉल करना होगा. जैसे, इस उदाहरण में दोनों जगहों पर नई एंट्री बनाई गई है. इस तरह किए गए एक साथ अपडेट, ऐटम की तरह होते हैं. इसका मतलब है कि या तो सभी अपडेट सफल होंगे या सभी अपडेट फ़ेल होंगे.
डेटा मिटाना
डेटा मिटाने का सबसे आसान तरीका यह है कि उस डेटा की जगह के रेफ़रंस पर RemoveValue() को कॉल किया जाए.
SetValue() या UpdateChildren() जैसी किसी अन्य कार्रवाई के लिए, वैल्यू के तौर पर null Variant तय करके भी डेटा मिटाया जा सकता है. UpdateChildren() के साथ इस तकनीक का इस्तेमाल करके, एपीआई को एक बार कॉल करके, कई चाइल्ड मिटाए जा सकते हैं.
जानें कि आपका डेटा कब सेव हुआ.
यह जानने के लिए कि आपका डेटा Firebase Realtime Database सर्वर पर कब सेव हुआ, सफलता के लिए फ़्यूचर का नतीजा देखें.
डेटा को लेन-देन के तौर पर सेव करना
अगर आपको ऐसे डेटा के साथ काम करना है जो एक साथ हो रहे
बदलावों की वजह से खराब हो सकता है, तो आप
लेन-देन की कार्रवाई का इस्तेमाल कर सकते हैं. जैसे, इंक्रीमेंटल काउंटर.
इस कार्रवाई के लिए, 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 क्लाइंट उस डेटा को रिमोट डेटाबेस सर्वर और अन्य क्लाइंट के साथ "बेस्ट-एफ़र्ट" के आधार पर सिंक करता है.
नतीजतन, डेटाबेस में सेव किए गए सभी डेटा से जुड़े लोकल इवेंट, सर्वर पर डेटा सेव होने से पहले ही ट्रिगर हो जाते हैं. इसका मतलब है कि नेटवर्क की लेटेन्सी या कनेक्टिविटी की वजह से, आपका ऐप्लिकेशन रिस्पॉन्सिव बना रहता है.
कनेक्शन फिर से बनने के बाद, आपके ऐप्लिकेशन को इवेंट का सही सेट मिलता है. इससे क्लाइंट, सर्वर की मौजूदा स्थिति के साथ सिंक हो जाता है. इसके लिए, कोई कस्टम कोड लिखने की ज़रूरत नहीं होती.