শুরু করুন
আপনি এখনও আপনার অ্যাপ এবং ডেটাবেসে অ্যাক্সেস সেট-আপ না করে থাকলে,
প্রথমে 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-এর মাধ্যমে গৃহীত ধরনগুলি একটি ভেরিয়েন্ট ধরনের মাধ্যমে পাস করতে পারেন যা নিম্নলিখিত বিষয়গুলি সাপোর্ট করে:
- Null (এটি ডেটা মুছে দেয়)
- পূর্ণসংখ্যা (৬৪-বিট)
- ডবল প্রিসিশন ফ্লোটিং পয়েন্ট নম্বর
- বুলিয়ান
- স্ট্রিং
- ভেরিয়েন্টের ভেক্টর
- Maps of strings to Variants
এইভাবে 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-এ ব্যবহারকারীর স্কোরে দ্বিতীয় এন্ট্রি তৈরি করতে
'কী' ব্যবহার করা যেতে পারে।
এইসব পাথ ব্যবহার করে, আপনি UpdateChildren()-এ একটি কল করে JSON ট্রির একাধিক লোকেশনে
একসাথে আপডেট করতে পারবেন, যেমন এই উদাহরণে
দুটি লোকেশনেই নতুন এন্ট্রি তৈরি করা হয়েছে। এইভাবে করা যুগপৎ আপডেটগুলি অ্যাটমিক: হয় সব আপডেট সফল হয় অথবা সব আপডেট ব্যর্থ হয়।
ডেটা মুছে দিন
ডেটা মুছে ফেলার সবচেয়ে সহজ উপায় হল, সেই ডেটার লোকেশনের রেফারেন্সে RemoveValue() কল করা।
এছাড়াও, আপনি SetValue() বা UpdateChildren()-এর মতো অন্য কোনও রাইট অপারেশনের জন্য ভ্যালু হিসেবে null Variant উল্লেখ করে মুছে দিতে পারেন। আপনি এই
টেকনিক UpdateChildren()-এর সাথে ব্যবহার করে একটি API কলের মাধ্যমে একাধিক বাচ্চার অ্যাকাউন্ট মুছে ফেলতে পারবেন।
আপনার ডেটা কখন কমিট করা হয় তা জানুন।
আপনার ডেটা কখন 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 ক্লায়েন্ট তখন রিমোট ডেটাবেস সার্ভার এবং অন্যান্য ক্লায়েন্টের সাথে "সর্বোচ্চ-চেষ্টা"র ভিত্তিতে সেই ডেটা সিঙ্ক করে।
এর ফলে, ডেটাবেসে কিছু লেখা হলে, সার্ভারে কোনও ডেটা লেখার আগেই, তা সাথে সাথে লোকাল ইভেন্ট ট্রিগার করে। এর অর্থ হল, নেটওয়ার্ক লেটেন্সি বা কানেক্টিভিটি যাই হোক না কেন, আপনার অ্যাপ রেসপন্সিভ থাকে।
কানেক্টিভিটি আবার প্রতিষ্ঠিত হলে, আপনার অ্যাপ উপযুক্ত সেট অফ ইভেন্ট পায় যাতে ক্লায়েন্ট বর্তমান সার্ভার স্টেট সিঙ্ক করে, কোনও কাস্টম কোড না লিখেই।