এই ডকুমেন্টে আপনার Firebase Realtime Database ডেটা লেখার চারটি পদ্ধতি আলোচনা করা হয়েছে: সেট, আপডেট, পুশ এবং ট্রানজ্যাকশন সাপোর্ট।
ডেটা সংরক্ষণের উপায়
| সেট | একটি নির্দিষ্ট পাথে ডেটা লিখুন বা প্রতিস্থাপন করুন, যেমন messages/users/<username> |
| আপডেট | সমস্ত ডেটা প্রতিস্থাপন না করে একটি নির্দিষ্ট পাথের কিছু কী আপডেট করুন। |
| ধাক্কা | ডাটাবেসের ডেটার তালিকায় যোগ করুন । প্রতিবার যখন আপনি তালিকায় একটি নতুন নোড যুক্ত করেন, আপনার ডাটাবেস একটি অনন্য কী (unique key) তৈরি করে, যেমন messages/users/<unique-user-id>/<username> |
| লেনদেন | জটিল ডেটা নিয়ে কাজ করার সময় ট্রানজ্যাকশন ব্যবহার করুন, কারণ যুগপৎ আপডেটের ফলে ডেটা নষ্ট হয়ে যেতে পারে। |
ডেটা সংরক্ষণ করা হচ্ছে
বেসিক ডাটাবেস রাইট অপারেশন হলো একটি সেট, যা নির্দিষ্ট ডাটাবেস রেফারেন্সে নতুন ডেটা সংরক্ষণ করে এবং সেই পাথে থাকা বিদ্যমান ডেটাকে প্রতিস্থাপন করে। সেট সম্পর্কে বোঝার জন্য, আমরা একটি সাধারণ ব্লগিং অ্যাপ তৈরি করব। আপনার অ্যাপের ডেটা এই ডাটাবেস রেফারেন্সে সংরক্ষিত থাকে:
জাভা
final FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("server/saving-data/fireblog");
নোড.জেএস
// Import Admin SDK const { getDatabase } = require('firebase-admin/database'); // Get a database reference to our blog const db = getDatabase(); const ref = db.ref('server/saving-data/fireblog');
পাইথন
# Import database module. from firebase_admin import db # Get a database reference to our blog. ref = db.reference('server/saving-data/fireblog')
যান
// Create a database client from App. client, err := app.Database(ctx) if err != nil { log.Fatalln("Error initializing database client:", err) } // Get a database reference to our blog. ref := client.NewRef("server/saving-data/fireblog")
চলুন কিছু ব্যবহারকারীর ডেটা সংরক্ষণ করে শুরু করা যাক। আমরা প্রতিটি ব্যবহারকারীকে একটি অনন্য ইউজারনেম দিয়ে সংরক্ষণ করব এবং তাদের পুরো নাম ও জন্ম তারিখও সংরক্ষণ করব। যেহেতু প্রতিটি ব্যবহারকারীর একটি অনন্য ইউজারনেম থাকবে, তাই এখানে push মেথডের পরিবর্তে set মেথড ব্যবহার করাই যুক্তিযুক্ত, কারণ আপনার কাছে ইতিমধ্যেই key আছে এবং নতুন করে তৈরি করার প্রয়োজন নেই।
প্রথমে, আপনার ব্যবহারকারীর ডেটার জন্য একটি ডাটাবেস রেফারেন্স তৈরি করুন। তারপর, ব্যবহারকারীর ইউজারনেম, পুরো নাম এবং জন্মতারিখ সহ একটি ইউজার অবজেক্ট ডাটাবেসে সংরক্ষণ করতে set() / setValue() ব্যবহার করুন। আপনি set-এ একটি স্ট্রিং, সংখ্যা, বুলিয়ান, null , অ্যারে বা যেকোনো JSON অবজেক্ট পাস করতে পারেন। null পাস করলে নির্দিষ্ট স্থানের ডেটা মুছে যাবে। এই ক্ষেত্রে আপনি এটিকে একটি অবজেক্ট পাস করবেন:
জাভা
public static class User { public String date_of_birth; public String full_name; public String nickname; public User(String dateOfBirth, String fullName) { // ... } public User(String dateOfBirth, String fullName, String nickname) { // ... } } DatabaseReference usersRef = ref.child("users"); Map<String, User> users = new HashMap<>(); users.put("alanisawesome", new User("June 23, 1912", "Alan Turing")); users.put("gracehop", new User("December 9, 1906", "Grace Hopper")); usersRef.setValueAsync(users);
নোড.জেএস
const usersRef = ref.child('users'); usersRef.set({ alanisawesome: { date_of_birth: 'June 23, 1912', full_name: 'Alan Turing' }, gracehop: { date_of_birth: 'December 9, 1906', full_name: 'Grace Hopper' } });
পাইথন
users_ref = ref.child('users') users_ref.set({ 'alanisawesome': { 'date_of_birth': 'June 23, 1912', 'full_name': 'Alan Turing' }, 'gracehop': { 'date_of_birth': 'December 9, 1906', 'full_name': 'Grace Hopper' } })
যান
// User is a json-serializable type. type User struct { DateOfBirth string `json:"date_of_birth,omitempty"` FullName string `json:"full_name,omitempty"` Nickname string `json:"nickname,omitempty"` } usersRef := ref.Child("users") err := usersRef.Set(ctx, map[string]*User{ "alanisawesome": { DateOfBirth: "June 23, 1912", FullName: "Alan Turing", }, "gracehop": { DateOfBirth: "December 9, 1906", FullName: "Grace Hopper", }, }) if err != nil { log.Fatalln("Error setting value:", err) }
যখন একটি JSON অবজেক্ট ডাটাবেসে সেভ করা হয়, তখন অবজেক্টের প্রোপার্টিগুলো স্বয়ংক্রিয়ভাবে নেস্টেড পদ্ধতিতে ডাটাবেসের চাইল্ড লোকেশনগুলোতে ম্যাপ হয়ে যায়। এখন যদি আপনি https://docs-examples.firebaseio.com/server/saving-data/fireblog/users/alanisawesome/full_name এই URL-টিতে যান, তাহলে আমরা "Alan Turing" ভ্যালুটি দেখতে পাব। আপনি সরাসরি একটি চাইল্ড লোকেশনেও ডেটা সেভ করতে পারেন:
জাভা
usersRef.child("alanisawesome").setValueAsync(new User("June 23, 1912", "Alan Turing")); usersRef.child("gracehop").setValueAsync(new User("December 9, 1906", "Grace Hopper"));
নোড.জেএস
const usersRef = ref.child('users'); usersRef.child('alanisawesome').set({ date_of_birth: 'June 23, 1912', full_name: 'Alan Turing' }); usersRef.child('gracehop').set({ date_of_birth: 'December 9, 1906', full_name: 'Grace Hopper' });
পাইথন
users_ref.child('alanisawesome').set({ 'date_of_birth': 'June 23, 1912', 'full_name': 'Alan Turing' }) users_ref.child('gracehop').set({ 'date_of_birth': 'December 9, 1906', 'full_name': 'Grace Hopper' })
যান
if err := usersRef.Child("alanisawesome").Set(ctx, &User{ DateOfBirth: "June 23, 1912", FullName: "Alan Turing", }); err != nil { log.Fatalln("Error setting value:", err) } if err := usersRef.Child("gracehop").Set(ctx, &User{ DateOfBirth: "December 9, 1906", FullName: "Grace Hopper", }); err != nil { log.Fatalln("Error setting value:", err) }
উপরের দুটি উদাহরণে — অর্থাৎ, উভয় মান একই সাথে একটি অবজেক্ট হিসাবে লেখা এবং সেগুলিকে আলাদাভাবে চাইল্ড লোকেশনে লেখা — এর ফলে আপনার ডাটাবেসে একই ডেটা সংরক্ষিত হবে:
{
"users": {
"alanisawesome": {
"date_of_birth": "June 23, 1912",
"full_name": "Alan Turing"
},
"gracehop": {
"date_of_birth": "December 9, 1906",
"full_name": "Grace Hopper"
}
}
}প্রথম উদাহরণটি ডেটা পর্যবেক্ষণকারী ক্লায়েন্টদের উপর শুধুমাত্র একটি ইভেন্ট ট্রিগার করবে, যেখানে দ্বিতীয় উদাহরণটি দুটি ইভেন্ট ট্রিগার করবে। এটি মনে রাখা গুরুত্বপূর্ণ যে, যদি usersRef এ আগে থেকেই ডেটা বিদ্যমান থাকে, তবে প্রথম পদ্ধতিটি তা ওভাররাইট করে দেবে, কিন্তু দ্বিতীয় পদ্ধতিটি usersRef এর অন্যান্য চাইল্ড নোডগুলোকে অপরিবর্তিত রেখে শুধুমাত্র প্রতিটি পৃথক চাইল্ড নোডের মান পরিবর্তন করবে।
সংরক্ষিত ডেটা আপডেট করা হচ্ছে
যদি আপনি অন্য চাইল্ড নোডগুলোকে ওভাররাইট না করে একই সাথে কোনো ডাটাবেস লোকেশনের একাধিক চাইল্ডে লিখতে চান, তাহলে আপনি নিচে দেখানো update মেথডটি ব্যবহার করতে পারেন:
জাভা
DatabaseReference hopperRef = usersRef.child("gracehop"); Map<String, Object> hopperUpdates = new HashMap<>(); hopperUpdates.put("nickname", "Amazing Grace"); hopperRef.updateChildrenAsync(hopperUpdates);
নোড.জেএস
const usersRef = ref.child('users'); const hopperRef = usersRef.child('gracehop'); hopperRef.update({ 'nickname': 'Amazing Grace' });
পাইথন
hopper_ref = users_ref.child('gracehop') hopper_ref.update({ 'nickname': 'Amazing Grace' })
যান
hopperRef := usersRef.Child("gracehop") if err := hopperRef.Update(ctx, map[string]interface{}{ "nickname": "Amazing Grace", }); err != nil { log.Fatalln("Error updating child:", err) }
এটি গ্রেসের ডেটা আপডেট করে তার ডাকনাম অন্তর্ভুক্ত করবে। আপনি যদি এখানে আপডেটের পরিবর্তে সেট ব্যবহার করতেন, তাহলে এটি আপনার hopperRef থেকে full_name এবং date_of_birth উভয়ই মুছে দিত।
Firebase Realtime Database মাল্টি-পাথ আপডেটও সমর্থন করে। এর মানে হলো, এখন একটি আপডেট আপনার ডেটাবেসের একাধিক স্থানে একই সময়ে ভ্যালু আপডেট করতে পারে, যা একটি শক্তিশালী ফিচার এবং এটি আপনার ডেটাকে ডিনরমালাইজ করতে সাহায্য করে। মাল্টি-পাথ আপডেট ব্যবহার করে, আপনি একই সাথে গ্রেস এবং অ্যালান উভয়ের জন্য ডাকনাম যোগ করতে পারেন:
জাভা
Map<String, Object> userUpdates = new HashMap<>(); userUpdates.put("alanisawesome/nickname", "Alan The Machine"); userUpdates.put("gracehop/nickname", "Amazing Grace"); usersRef.updateChildrenAsync(userUpdates);
নোড.জেএস
const usersRef = ref.child('users'); usersRef.update({ 'alanisawesome/nickname': 'Alan The Machine', 'gracehop/nickname': 'Amazing Grace' });
পাইথন
users_ref.update({ 'alanisawesome/nickname': 'Alan The Machine', 'gracehop/nickname': 'Amazing Grace' })
যান
if err := usersRef.Update(ctx, map[string]interface{}{ "alanisawesome/nickname": "Alan The Machine", "gracehop/nickname": "Amazing Grace", }); err != nil { log.Fatalln("Error updating children:", err) }
এই আপডেটের পর অ্যালান এবং গ্রেস উভয়েরই ডাকনাম যোগ করা হয়েছে:
{
"users": {
"alanisawesome": {
"date_of_birth": "June 23, 1912",
"full_name": "Alan Turing",
"nickname": "Alan The Machine"
},
"gracehop": {
"date_of_birth": "December 9, 1906",
"full_name": "Grace Hopper",
"nickname": "Amazing Grace"
}
}
}মনে রাখবেন যে, পাথ সহ অবজেক্ট লিখে তা আপডেট করার চেষ্টা করলে ভিন্ন আচরণ দেখা যাবে। চলুন দেখে নেওয়া যাক, এর পরিবর্তে আপনি যদি গ্রেস এবং অ্যালানকে এইভাবে আপডেট করার চেষ্টা করেন তাহলে কী ঘটে:
জাভা
Map<String, Object> userNicknameUpdates = new HashMap<>(); userNicknameUpdates.put("alanisawesome", new User(null, null, "Alan The Machine")); userNicknameUpdates.put("gracehop", new User(null, null, "Amazing Grace")); usersRef.updateChildrenAsync(userNicknameUpdates);
নোড.জেএস
const usersRef = ref.child('users'); usersRef.update({ 'alanisawesome': { 'nickname': 'Alan The Machine' }, 'gracehop': { 'nickname': 'Amazing Grace' } });
পাইথন
users_ref.update({ 'alanisawesome': { 'nickname': 'Alan The Machine' }, 'gracehop': { 'nickname': 'Amazing Grace' } })
যান
if err := usersRef.Update(ctx, map[string]interface{}{ "alanisawesome": &User{Nickname: "Alan The Machine"}, "gracehop": &User{Nickname: "Amazing Grace"}, }); err != nil { log.Fatalln("Error updating children:", err) }
এর ফলে ভিন্ন আচরণ দেখা যায়, অর্থাৎ সম্পূর্ণ /users নোডটি ওভাররাইট হয়ে যায়:
{
"users": {
"alanisawesome": {
"nickname": "Alan The Machine"
},
"gracehop": {
"nickname": "Amazing Grace"
}
}
}একটি সমাপ্তি কলব্যাক যোগ করা
Node.js এবং Java অ্যাডমিন SDK-তে, আপনার ডেটা কখন কমিট করা হয়েছে তা জানতে চাইলে, আপনি একটি কমপ্লিশন কলব্যাক যোগ করতে পারেন। এই SDK-গুলোর set এবং update উভয় মেথডেই একটি ঐচ্ছিক কমপ্লিশন কলব্যাক থাকে, যা ডেটাবেসে রাইট কমিট হয়ে গেলে কল করা হয়। কোনো কারণে কলটি অসফল হলে, ব্যর্থতার কারণ নির্দেশ করে একটি এরর অবজেক্ট কলব্যাকে পাঠানো হয়। Python এবং Go অ্যাডমিন SDK-তে, সমস্ত write মেথডই ব্লকিং। অর্থাৎ, ডেটাবেসে রাইট কমিট না হওয়া পর্যন্ত write মেথডগুলো রিটার্ন করে না।
জাভা
DatabaseReference dataRef = ref.child("data"); dataRef.setValue("I'm writing data", new DatabaseReference.CompletionListener() { @Override public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) { if (databaseError != null) { System.out.println("Data could not be saved " + databaseError.getMessage()); } else { System.out.println("Data saved successfully."); } } });
নোড.জেএস
dataRef.set('I\'m writing data', (error) => { if (error) { console.log('Data could not be saved.' + error); } else { console.log('Data saved successfully.'); } });
ডেটার তালিকা সংরক্ষণ করা
ডেটার তালিকা তৈরি করার সময়, বেশিরভাগ অ্যাপ্লিকেশনের বহু-ব্যবহারকারী প্রকৃতির কথা মাথায় রাখা এবং সেই অনুযায়ী আপনার তালিকার কাঠামো সামঞ্জস্য করা গুরুত্বপূর্ণ। উপরের উদাহরণটিকে আরও বিস্তৃত করে, চলুন আপনার অ্যাপে ব্লগ পোস্ট যুক্ত করি। আপনার প্রথম প্রবৃত্তি হতে পারে স্বয়ংক্রিয়ভাবে বৃদ্ধি পাওয়া পূর্ণসংখ্যা সূচক সহ চাইল্ড ভেরিয়েবলগুলো সংরক্ষণ করতে 'সেট' ব্যবহার করা, যেমনটি নিচে দেখানো হলো:
// NOT RECOMMENDED - use push() instead! { "posts": { "0": { "author": "gracehop", "title": "Announcing COBOL, a New Programming Language" }, "1": { "author": "alanisawesome", "title": "The Turing Machine" } } }
যদি কোনো ব্যবহারকারী একটি নতুন পোস্ট যোগ করেন, তবে সেটি /posts/2 হিসেবে সংরক্ষিত হবে। যদি কেবল একজন লেখকই পোস্ট যোগ করতেন, তবে এটি কাজ করত, কিন্তু আপনার সহযোগী ব্লগিং অ্যাপ্লিকেশনে অনেক ব্যবহারকারী একই সময়ে পোস্ট যোগ করতে পারেন। যদি দুইজন লেখক একই সাথে /posts/2 এ লেখেন, তবে একজনের পোস্ট অন্যজন মুছে দেবেন।
এই সমস্যা সমাধানের জন্য, ফায়ারবেস ক্লায়েন্টগুলো একটি push() ফাংশন প্রদান করে যা প্রতিটি নতুন `child`-এর জন্য একটি অনন্য `key` তৈরি করে । অনন্য `child key` ব্যবহার করার ফলে, একাধিক ক্লায়েন্ট `write conflict`-এর চিন্তা ছাড়াই একই সময়ে একই লোকেশনে `child` যোগ করতে পারে।
জাভা
public static class Post { public String author; public String title; public Post(String author, String title) { // ... } } DatabaseReference postsRef = ref.child("posts"); DatabaseReference newPostRef = postsRef.push(); newPostRef.setValueAsync(new Post("gracehop", "Announcing COBOL, a New Programming Language")); // We can also chain the two calls together postsRef.push().setValueAsync(new Post("alanisawesome", "The Turing Machine"));
নোড.জেএস
const newPostRef = postsRef.push(); newPostRef.set({ author: 'gracehop', title: 'Announcing COBOL, a New Programming Language' }); // we can also chain the two calls together postsRef.push().set({ author: 'alanisawesome', title: 'The Turing Machine' });
পাইথন
posts_ref = ref.child('posts') new_post_ref = posts_ref.push() new_post_ref.set({ 'author': 'gracehop', 'title': 'Announcing COBOL, a New Programming Language' }) # We can also chain the two calls together posts_ref.push().set({ 'author': 'alanisawesome', 'title': 'The Turing Machine' })
যান
// Post is a json-serializable type. type Post struct { Author string `json:"author,omitempty"` Title string `json:"title,omitempty"` } postsRef := ref.Child("posts") newPostRef, err := postsRef.Push(ctx, nil) if err != nil { log.Fatalln("Error pushing child node:", err) } if err := newPostRef.Set(ctx, &Post{ Author: "gracehop", Title: "Announcing COBOL, a New Programming Language", }); err != nil { log.Fatalln("Error setting value:", err) } // We can also chain the two calls together if _, err := postsRef.Push(ctx, &Post{ Author: "alanisawesome", Title: "The Turing Machine", }); err != nil { log.Fatalln("Error pushing child node:", err) }
ইউনিক কী-টি একটি টাইমস্ট্যাম্পের উপর ভিত্তি করে তৈরি, তাই তালিকার আইটেমগুলো স্বয়ংক্রিয়ভাবে কালানুক্রমিকভাবে সাজানো হবে। যেহেতু ফায়ারবেস প্রতিটি ব্লগ পোস্টের জন্য একটি ইউনিক কী তৈরি করে, তাই একাধিক ব্যবহারকারী একই সময়ে একটি পোস্ট যোগ করলেও কোনো রাইট কনফ্লিক্ট ঘটবে না। আপনার ডাটাবেসের ডেটা এখন দেখতে এইরকম:
{
"posts": {
"-JRHTHaIs-jNPLXOQivY": {
"author": "gracehop",
"title": "Announcing COBOL, a New Programming Language"
},
"-JRHTHaKuITFIhnj02kE": {
"author": "alanisawesome",
"title": "The Turing Machine"
}
}
}জাভাস্ক্রিপ্ট, পাইথন এবং গো-তে push() কল করার পর পরই ` set() কল করার রীতিটি এতটাই প্রচলিত যে, ফায়ারবেস এসডিকে আপনাকে এই দুটিকে একত্রিত করার সুযোগ দেয়। এর জন্য আপনাকে সেট করার ডেটা সরাসরি ` push() এ পাস করতে হবে, যা নিম্নরূপ:
জাভা
// No Java equivalentনোড.জেএস
// This is equivalent to the calls to push().set(...) above postsRef.push({ author: 'gracehop', title: 'Announcing COBOL, a New Programming Language' });;
পাইথন
# This is equivalent to the calls to push().set(...) above posts_ref.push({ 'author': 'gracehop', 'title': 'Announcing COBOL, a New Programming Language' })
যান
if _, err := postsRef.Push(ctx, &Post{ Author: "gracehop", Title: "Announcing COBOL, a New Programming Language", }); err != nil { log.Fatalln("Error pushing child node:", err) }
push() দ্বারা তৈরি অনন্য কী পাওয়া যাচ্ছে
` push() ` কল করলে নতুন ডেটা পাথের একটি রেফারেন্স ফেরত আসবে, যা ব্যবহার করে আপনি কী (key) পেতে বা তাতে ডেটা সেট করতে পারবেন। নিচের কোডটির ফলে উপরের উদাহরণের মতোই একই ডেটা পাওয়া যাবে, কিন্তু এখন আমরা তৈরি হওয়া ইউনিক কী-টি অ্যাক্সেস করতে পারব:
জাভা
// Generate a reference to a new location and add some data using push() DatabaseReference pushedPostRef = postsRef.push(); // Get the unique ID generated by a push() String postId = pushedPostRef.getKey();
নোড.জেএস
// Generate a reference to a new location and add some data using push() const newPostRef = postsRef.push(); // Get the unique key generated by push() const postId = newPostRef.key;
পাইথন
# Generate a reference to a new location and add some data using push() new_post_ref = posts_ref.push() # Get the unique key generated by push() post_id = new_post_ref.key
যান
// Generate a reference to a new location and add some data using Push() newPostRef, err := postsRef.Push(ctx, nil) if err != nil { log.Fatalln("Error pushing child node:", err) } // Get the unique key generated by Push() postID := newPostRef.Key
যেমনটি দেখতে পাচ্ছেন, আপনি আপনার push() রেফারেন্স থেকে ইউনিক কী-এর মান পেতে পারেন।
ডেটা পুনরুদ্ধার সম্পর্কিত পরবর্তী অংশে, আমরা শিখব কীভাবে একটি ফায়ারবেস ডাটাবেস থেকে এই ডেটা পড়তে হয়।
লেনদেন সংক্রান্ত তথ্য সংরক্ষণ করা
একই সাথে একাধিক পরিবর্তনের ফলে বিকৃত হতে পারে এমন জটিল ডেটা, যেমন ইনক্রিমেন্টাল কাউন্টার, নিয়ে কাজ করার সময় SDK একটি ট্রানজ্যাকশন অপারেশন প্রদান করে।
জাভা এবং নোড.জেএস-এ, ট্রানজ্যাকশন অপারেশনে দুটি কলব্যাক দেওয়া হয়: একটি আপডেট ফাংশন এবং একটি ঐচ্ছিক কমপ্লিশন কলব্যাক। পাইথন এবং গো-তে, ট্রানজ্যাকশন অপারেশনটি ব্লকিং হওয়ায় এটি শুধুমাত্র আপডেট ফাংশনটি গ্রহণ করে।
আপডেট ফাংশনটি আর্গুমেন্ট হিসেবে ডেটার বর্তমান অবস্থা গ্রহণ করে এবং আপনার কাঙ্ক্ষিত নতুন অবস্থাটি রিটার্ন করে। উদাহরণস্বরূপ, যদি আপনি কোনো নির্দিষ্ট ব্লগ পোস্টের আপভোটের সংখ্যা বাড়াতে চান, তাহলে আপনাকে নিচের মতো একটি ট্রানজ্যাকশন লিখতে হবে:
জাভা
DatabaseReference upvotesRef = ref.child("server/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes"); upvotesRef.runTransaction(new Transaction.Handler() { @Override public Transaction.Result doTransaction(MutableData mutableData) { Integer currentValue = mutableData.getValue(Integer.class); if (currentValue == null) { mutableData.setValue(1); } else { mutableData.setValue(currentValue + 1); } return Transaction.success(mutableData); } @Override public void onComplete( DatabaseError databaseError, boolean committed, DataSnapshot dataSnapshot) { System.out.println("Transaction completed"); } });
নোড.জেএস
const upvotesRef = db.ref('server/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes'); upvotesRef.transaction((current_value) => { return (current_value || 0) + 1; });
পাইথন
def increment_votes(current_value): return current_value + 1 if current_value else 1 upvotes_ref = db.reference('server/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes') try: new_vote_count = upvotes_ref.transaction(increment_votes) print('Transaction completed') except db.TransactionAbortedError: print('Transaction failed to commit')
যান
fn := func(t db.TransactionNode) (interface{}, error) { var currentValue int if err := t.Unmarshal(¤tValue); err != nil { return nil, err } return currentValue + 1, nil } ref := client.NewRef("server/saving-data/fireblog/posts/-JRHTHaIs-jNPLXOQivY/upvotes") if err := ref.Transaction(ctx, fn); err != nil { log.Fatalln("Transaction failed to commit:", err) }
উপরের উদাহরণটি পরীক্ষা করে দেখে যে কাউন্টারটি null কিনা বা এখনও বাড়ানো হয়নি কিনা, কারণ কোনো ডিফল্ট মান লেখা না থাকলে ট্রানজ্যাকশনগুলো null দিয়েও কল করা যেতে পারে।
যদি উপরের কোডটি কোনো ট্রানজ্যাকশন ফাংশন ছাড়া চালানো হতো এবং দুজন ক্লায়েন্ট একই সাথে এর মান বাড়ানোর চেষ্টা করত, তাহলে তারা উভয়েই নতুন মান হিসেবে 1 লিখত, যার ফলে দুইবারের পরিবর্তে একবারই মান বাড়ত।
নেটওয়ার্ক সংযোগ এবং অফলাইন লেখা
ফায়ারবেস নোড.জেএস এবং জাভা ক্লায়েন্টরা যেকোনো সক্রিয় ডেটার নিজস্ব অভ্যন্তরীণ সংস্করণ বজায় রাখে। যখন ডেটা লেখা হয়, তখন তা প্রথমে এই স্থানীয় সংস্করণে লেখা হয়। এরপর ক্লায়েন্ট 'সর্বোত্তম প্রচেষ্টা'র ভিত্তিতে সেই ডেটা ডেটাবেস এবং অন্যান্য ক্লায়েন্টের সাথে সিঙ্ক্রোনাইজ করে।
এর ফলে, ডেটাবেসে কোনো ডেটা লেখা হওয়ার আগেই, ডেটাবেসে করা সমস্ত রাইট অপারেশন তাৎক্ষণিকভাবে লোকাল ইভেন্ট ট্রিগার করবে। এর মানে হলো, আপনি যখন ফায়ারবেস ব্যবহার করে কোনো অ্যাপ্লিকেশন তৈরি করবেন, তখন নেটওয়ার্ক ল্যাটেন্সি বা ইন্টারনেট কানেক্টিভিটি নির্বিশেষে আপনার অ্যাপটি রেসপন্সিভ থাকবে।
সংযোগ পুনঃপ্রতিষ্ঠিত হলে, আমরা প্রয়োজনীয় ইভেন্টগুলো পাবো, যাতে ক্লায়েন্ট কোনো কাস্টম কোড না লিখেই সার্ভারের বর্তমান অবস্থার সাথে তাল মিলিয়ে চলতে পারে।
আপনার ডেটা সুরক্ষিত করা
Firebase Realtime Database একটি নিরাপত্তা ভাষা রয়েছে, যা আপনাকে নির্ধারণ করতে দেয় যে কোন ব্যবহারকারীরা আপনার ডেটার বিভিন্ন নোডে রিড এবং রাইট অ্যাক্সেস পাবে। আপনি "আপনার ডেটা সুরক্ষিত করুন" অংশে এ সম্পর্কে আরও পড়তে পারেন।