তথ্য উদ্ধার করা হচ্ছে

এই ডকুমেন্টটি ডাটাবেস ডেটা পুনরুদ্ধারের মূল বিষয়গুলি কভার করে, কীভাবে ডেটা অর্ডার করা হয় এবং কীভাবে ডেটাতে সাধারণ প্রশ্নগুলি সম্পাদন করা যায়। অ্যাডমিন SDK-এ ডেটা পুনরুদ্ধার বিভিন্ন প্রোগ্রামিং ভাষায় কিছুটা ভিন্নভাবে প্রয়োগ করা হয়।

  1. অ্যাসিঙ্ক্রোনাস শ্রোতা: একটি Firebase Realtime Database সংরক্ষিত ডেটা একটি ডাটাবেস রেফারেন্সের সাথে একটি অ্যাসিঙ্ক্রোনাস শ্রোতা সংযুক্ত করে পুনরুদ্ধার করা হয়। শ্রোতা ডেটার প্রাথমিক অবস্থার জন্য একবার ট্রিগার হয় এবং আবার যে কোনও সময় ডেটা পরিবর্তন হয়। একজন ইভেন্ট শ্রোতা বিভিন্ন ধরনের ইভেন্ট পেতে পারে। ডেটা পুনরুদ্ধারের এই মোডটি Java, Node.js এবং Python Admin SDK-তে সমর্থিত।
  2. ব্লকিং রিডস: একটি Firebase Realtime Database সংরক্ষিত ডেটা একটি ডাটাবেস রেফারেন্সে একটি ব্লকিং পদ্ধতি ব্যবহার করে পুনরুদ্ধার করা হয়, যা রেফারেন্সে সংরক্ষিত ডেটা ফেরত দেয়। প্রতিটি পদ্ধতি কল একটি এককালীন অপারেশন. তার মানে SDK কোনো কলব্যাক রেজিস্টার করে না যা পরবর্তী ডেটা আপডেট শুনতে পায়। ডেটা পুনরুদ্ধারের এই মডেলটি Python এবং Go Admin SDK-তে সমর্থিত।

শুরু করা

ফায়ারবেস ডাটাবেস থেকে ডেটা কীভাবে পড়তে হয় তা বোঝার জন্য আগের নিবন্ধ থেকে ব্লগিং উদাহরণটি আবার দেখুন। মনে রাখবেন যে উদাহরণ অ্যাপের ব্লগ পোস্টগুলি ডাটাবেস URL https://docs-examples.firebaseio.com/server/saving-data/fireblog/posts.json এ সংরক্ষণ করা হয়েছে। আপনার পোস্ট ডেটা পড়তে, আপনি নিম্নলিখিতগুলি করতে পারেন:

জাভা
public static class Post {

  public String author;
  public String title;

  public Post(String author, String title) {
    // ...
  }

}

// Get a reference to our posts
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("server/saving-data/fireblog/posts");

// Attach a listener to read the data at our posts reference
ref.addValueEventListener(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot dataSnapshot) {
    Post post = dataSnapshot.getValue(Post.class);
    System.out.println(post);
  }

  @Override
  public void onCancelled(DatabaseError databaseError) {
    System.out.println("The read failed: " + databaseError.getCode());
  }
});
Node.js
// Get a database reference to our posts
const db = getDatabase();
const ref = db.ref('server/saving-data/fireblog/posts');

// Attach an asynchronous callback to read the data at our posts reference
ref.on('value', (snapshot) => {
  console.log(snapshot.val());
}, (errorObject) => {
  console.log('The read failed: ' + errorObject.name);
}); 
পাইথন
# Import database module.
from firebase_admin import db

# Get a database reference to our posts
ref = db.reference('server/saving-data/fireblog/posts')

# Read the data at the posts reference (this is a blocking operation)
print(ref.get())
যাও
// Post is a json-serializable type.
type Post struct {
	Author string `json:"author,omitempty"`
	Title  string `json:"title,omitempty"`
}

// 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 posts
ref := client.NewRef("server/saving-data/fireblog/posts")

// Read the data at the posts reference (this is a blocking operation)
var post Post
if err := ref.Get(ctx, &post); err != nil {
	log.Fatalln("Error reading value:", err)
}

আপনি যদি উপরের কোডটি চালান, আপনি কনসোলে লগ করা আপনার সমস্ত পোস্ট ধারণকারী একটি বস্তু দেখতে পাবেন। Node.js এবং Java এর ক্ষেত্রে, আপনার ডাটাবেস রেফারেন্সে নতুন ডেটা যোগ করা হলে লিসেনার ফাংশন বলা হয় এবং এটি ঘটানোর জন্য আপনাকে কোনো অতিরিক্ত কোড লিখতে হবে না।

Java এবং Node.js-এ, কলব্যাক ফাংশন একটি DataSnapshot পায়, যা ডেটার একটি স্ন্যাপশট। একটি স্ন্যাপশট হল একটি নির্দিষ্ট ডাটাবেস রেফারেন্সে একক সময়ে ডেটার একটি ছবি। একটি স্ন্যাপশটে val() / getValue() কল করা ডেটার একটি ভাষা-নির্দিষ্ট বস্তুর উপস্থাপনা প্রদান করে। যদি রেফারেন্সের অবস্থানে কোনো ডেটা বিদ্যমান না থাকে, তাহলে স্ন্যাপশটের মান null হয়। পাইথনের get() পদ্ধতি সরাসরি ডেটার একটি পাইথন উপস্থাপনা প্রদান করে। Go-তে Get() ফাংশন একটি প্রদত্ত ডেটা স্ট্রাকচারে ডেটা আনমার্শাল করে।

লক্ষ্য করুন যে আমরা উপরের উদাহরণে value ইভেন্ট টাইপ ব্যবহার করেছি, যা একটি ফায়ারবেস ডাটাবেসের রেফারেন্সের সম্পূর্ণ বিষয়বস্তু পড়ে, এমনকি যদি শুধুমাত্র একটি ডেটা পরিবর্তিত হয়। value হল নীচে তালিকাভুক্ত পাঁচটি ভিন্ন ইভেন্টের একটি যা আপনি ডাটাবেস থেকে ডেটা পড়তে ব্যবহার করতে পারেন।

Java এবং Node.js-এ ইভেন্টের ধরন পড়ুন

মান

value ইভেন্টটি একটি প্রদত্ত ডাটাবেস পাথে বিষয়বস্তুর একটি স্ট্যাটিক স্ন্যাপশট পড়ার জন্য ব্যবহৃত হয়, কারণ সেগুলি পঠিত ইভেন্টের সময় বিদ্যমান ছিল। এটি প্রাথমিক ডেটার সাথে একবার ট্রিগার হয় এবং প্রতিবার ডেটা পরিবর্তিত হয়। ইভেন্ট কলব্যাক একটি স্ন্যাপশট পাস করা হয় যেখানে শিশু ডেটা সহ সেই অবস্থানের সমস্ত ডেটা রয়েছে৷ উপরের কোড উদাহরণে, value আপনার অ্যাপের সমস্ত ব্লগ পোস্ট ফিরিয়ে দিয়েছে। প্রতিবার একটি নতুন ব্লগ পোস্ট যোগ করা হলে, কলব্যাক ফাংশন সমস্ত পোস্ট ফিরিয়ে দেবে।

শিশু যোগ করা হয়েছে

ডাটাবেস থেকে আইটেমগুলির একটি তালিকা পুনরুদ্ধার করার সময় child_added ইভেন্টটি সাধারণত ব্যবহৃত হয়। value বিপরীতে যা অবস্থানের সম্পূর্ণ বিষয়বস্তু প্রদান করে, child_added প্রতিটি বিদ্যমান শিশুর জন্য একবার ট্রিগার করা হয় এবং তারপরে প্রতিবার নির্দিষ্ট পথে একটি নতুন শিশু যুক্ত করা হয়। ইভেন্ট কলব্যাক নতুন সন্তানের ডেটা সম্বলিত একটি স্ন্যাপশট পাস করা হয়। আদেশের উদ্দেশ্যে, এটি পূর্ববর্তী সন্তানের কী সম্বলিত একটি দ্বিতীয় যুক্তিও পাস করা হয়।

আপনি যদি আপনার ব্লগিং অ্যাপে যোগ করা প্রতিটি নতুন পোস্টের শুধুমাত্র ডেটা পুনরুদ্ধার করতে চান, তাহলে আপনি child_added ব্যবহার করতে পারেন :

জাভা
ref.addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    Post newPost = dataSnapshot.getValue(Post.class);
    System.out.println("Author: " + newPost.author);
    System.out.println("Title: " + newPost.title);
    System.out.println("Previous Post ID: " + prevChildKey);
  }

  @Override
  public void onChildChanged(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onChildRemoved(DataSnapshot dataSnapshot) {}

  @Override
  public void onChildMoved(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onCancelled(DatabaseError databaseError) {}
});
Node.js
// Retrieve new posts as they are added to our database
ref.on('child_added', (snapshot, prevChildKey) => {
  const newPost = snapshot.val();
  console.log('Author: ' + newPost.author);
  console.log('Title: ' + newPost.title);
  console.log('Previous Post ID: ' + prevChildKey);
});

এই উদাহরণে স্ন্যাপশটে একটি পৃথক ব্লগ পোস্ট সহ একটি বস্তু থাকবে। যেহেতু SDK মান পুনরুদ্ধার করে পোস্টগুলিকে বস্তুতে রূপান্তর করে, আপনি যথাক্রমে author এবং title কল করে পোস্টের লেখক এবং শিরোনামের বৈশিষ্ট্যগুলিতে অ্যাক্সেস পাবেন৷ দ্বিতীয় prevChildKey আর্গুমেন্ট থেকে আগের পোস্ট আইডিতেও আপনার অ্যাক্সেস আছে।

শিশু পরিবর্তিত

চাইল্ড নোড পরিবর্তন করা হলে child_changed ইভেন্টটি ট্রিগার হয়। এর মধ্যে চাইল্ড নোডের বংশধরদের যেকোনো পরিবর্তন অন্তর্ভুক্ত রয়েছে। আইটেমগুলির একটি তালিকায় পরিবর্তনের প্রতিক্রিয়া জানাতে এটি সাধারণত child_added এবং child_removed সাথে ব্যবহার করা হয়। ইভেন্ট কলব্যাকে পাস করা স্ন্যাপশটে সন্তানের জন্য আপডেট করা ডেটা রয়েছে।

আপনি যখন ব্লগ পোস্টগুলি সম্পাদনা করা হয় তখন আপডেট করা ডেটা পড়তে child_changed ব্যবহার করতে পারেন:

জাভা
ref.addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onChildChanged(DataSnapshot dataSnapshot, String prevChildKey) {
    Post changedPost = dataSnapshot.getValue(Post.class);
    System.out.println("The updated post title is: " + changedPost.title);
  }

  @Override
  public void onChildRemoved(DataSnapshot dataSnapshot) {}

  @Override
  public void onChildMoved(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onCancelled(DatabaseError databaseError) {}
});
Node.js
// Get the data on a post that has changed
ref.on('child_changed', (snapshot) => {
  const changedPost = snapshot.val();
  console.log('The updated post title is ' + changedPost.title);
});

শিশু অপসারিত

একটি অবিলম্বে শিশুকে সরানো হলে child_removed ঘটনাটি ট্রিগার হয়। এটি সাধারণত child_added এবং child_changed এর সাথে ব্যবহার করা হয়। ইভেন্ট কলব্যাকে পাস করা স্ন্যাপশটে সরানো সন্তানের ডেটা রয়েছে।

ব্লগের উদাহরণে, আপনি কনসোলে মুছে ফেলা পোস্ট সম্পর্কে একটি বিজ্ঞপ্তি লগ করতে child_removed ব্যবহার করতে পারেন:

জাভা
ref.addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onChildChanged(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onChildRemoved(DataSnapshot dataSnapshot) {
    Post removedPost = dataSnapshot.getValue(Post.class);
    System.out.println("The blog post titled " + removedPost.title + " has been deleted");
  }

  @Override
  public void onChildMoved(DataSnapshot dataSnapshot, String prevChildKey) {}

  @Override
  public void onCancelled(DatabaseError databaseError) {}
});
Node.js
// Get a reference to our posts
const ref = db.ref('server/saving-data/fireblog/posts');

// Get the data on a post that has been removed
ref.on('child_removed', (snapshot) => {
  const deletedPost = snapshot.val();
  console.log('The blog post titled \'' + deletedPost.title + '\' has been deleted');
});

শিশু সরানো হয়েছে

অর্ডার করা ডেটা নিয়ে কাজ করার সময় child_moved ইভেন্টটি ব্যবহার করা হয়, যা পরবর্তী বিভাগে কভার করা হয়েছে।

ইভেন্ট গ্যারান্টি

ফায়ারবেস ডাটাবেস ইভেন্ট সম্পর্কিত বেশ কয়েকটি গুরুত্বপূর্ণ গ্যারান্টি দেয়:

ডাটাবেস ইভেন্ট গ্যারান্টি
স্থানীয় রাষ্ট্র পরিবর্তন হলে ইভেন্টগুলি সর্বদা ট্রিগার হবে।
ইভেন্টগুলি সর্বদা অবশেষে ডেটার সঠিক অবস্থাকে প্রতিফলিত করবে, এমনকি এমন ক্ষেত্রে যেখানে স্থানীয় ক্রিয়াকলাপ বা সময় সাময়িক পার্থক্য সৃষ্টি করে, যেমন নেটওয়ার্ক সংযোগের সাময়িক ক্ষতি।
একটি একক ক্লায়েন্ট থেকে লেখা সর্বদা সার্ভারে লিখিত হবে এবং অন্য ব্যবহারকারীদের কাছে ক্রমানুসারে সম্প্রচার করা হবে।
মান ইভেন্টগুলি সর্বদা শেষ ট্রিগার হয় এবং সেই স্ন্যাপশট নেওয়ার আগে ঘটে যাওয়া অন্য কোনও ইভেন্ট থেকে আপডেটগুলি ধারণ করার গ্যারান্টি দেওয়া হয়।

যেহেতু মান ইভেন্টগুলি সর্বদা শেষ ট্রিগার হয়, নিম্নলিখিত উদাহরণটি সর্বদা কাজ করবে:

জাভা
final AtomicInteger count = new AtomicInteger();

ref.addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    // New child added, increment count
    int newCount = count.incrementAndGet();
    System.out.println("Added " + dataSnapshot.getKey() + ", count is " + newCount);
  }

  // ...
});

// The number of children will always be equal to 'count' since the value of
// the dataSnapshot here will include every child_added event triggered before this point.
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot dataSnapshot) {
    long numChildren = dataSnapshot.getChildrenCount();
    System.out.println(count.get() + " == " + numChildren);
  }

  @Override
  public void onCancelled(DatabaseError databaseError) {}
});
Node.js
let count = 0;

ref.on('child_added', (snap) => {
  count++;
  console.log('added:', snap.key);
});

// length will always equal count, since snap.val() will include every child_added event
// triggered before this point
ref.once('value', (snap) => {
  console.log('initial data loaded!', snap.numChildren() === count);
});

কলব্যাক বিচ্ছিন্ন করা

ইভেন্টের ধরন এবং যে কলব্যাক ফাংশনটি সরানো হবে তা উল্লেখ করে কলব্যাকগুলি সরানো হয়, যেমন:

জাভা
// Create and attach listener
ValueEventListener listener = new ValueEventListener() {
    // ...
};
ref.addValueEventListener(listener);

// Remove listener
ref.removeEventListener(listener);
Node.js
ref.off('value', originalCallback);

আপনি যদি on() এ একটি স্কোপ প্রসঙ্গ পাস করেন, তাহলে কলব্যাকটি বিচ্ছিন্ন করার সময় এটি অবশ্যই পাস করতে হবে:

জাভা
// Not applicable for Java
Node.js
ref.off('value', originalCallback, ctx);

আপনি যদি একটি অবস্থানে সমস্ত কলব্যাক অপসারণ করতে চান তবে আপনি নিম্নলিখিতগুলি করতে পারেন:

জাভা
// No Java equivalent, listeners must be removed individually.
Node.js
// Remove all value callbacks
ref.off('value');

// Remove all callbacks of any type
ref.off();

একবার ডেটা পড়া

কিছু ক্ষেত্রে এটি একটি কলব্যাক একবার কল করা এবং তারপর অবিলম্বে সরিয়ে ফেলার জন্য উপযোগী হতে পারে। এটি সহজ করার জন্য আমরা একটি সহায়ক ফাংশন তৈরি করেছি:

জাভা
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot dataSnapshot) {
    // ...
  }

  @Override
  public void onCancelled(DatabaseError databaseError) {
    // ...
  }
});
Node.js
ref.once('value', (data) => {
  // do some stuff once
});
পাইথন
# Import database module.
from firebase_admin import db

# Get a database reference to our posts
ref = db.reference('server/saving-data/fireblog/posts')

# Read the data at the posts reference (this is a blocking operation)
print(ref.get())
যাও
// 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 posts
ref := client.NewRef("server/saving-data/fireblog/posts")

// Read the data at the posts reference (this is a blocking operation)
var post Post
if err := ref.Get(ctx, &post); err != nil {
	log.Fatalln("Error reading value:", err)
}

তথ্য অনুসন্ধান

ফায়ারবেস ডাটাবেস কোয়েরির মাধ্যমে, আপনি বেছে বেছে বিভিন্ন কারণের উপর ভিত্তি করে ডেটা পুনরুদ্ধার করতে পারেন। আপনার ডাটাবেসে একটি ক্যোয়ারী তৈরি করতে, আপনি অর্ডার করার ফাংশনগুলির একটি ব্যবহার করে কীভাবে আপনার ডেটা অর্ডার করতে চান তা উল্লেখ করে শুরু করুন: orderByChild() , orderByKey() , অথবা orderByValue() । তারপর আপনি জটিল প্রশ্নগুলি পরিচালনা করার জন্য এইগুলিকে অন্য পাঁচটি পদ্ধতির সাথে একত্রিত করতে পারেন: limitToFirst() , limitToLast() , startAt() , endAt() , এবং equalTo()

যেহেতু ফায়ারবেসে আমরা সবাই মনে করি ডাইনোসরগুলি বেশ দুর্দান্ত, তাই আপনি কীভাবে আপনার ফায়ারবেস ডাটাবেসে ডেটা অনুসন্ধান করতে পারেন তা প্রদর্শন করতে আমরা ডাইনোসরের তথ্যের একটি নমুনা ডাটাবেস থেকে একটি স্নিপেট ব্যবহার করব৷:

{
  "lambeosaurus": {
    "height" : 2.1,
    "length" : 12.5,
    "weight": 5000
  },
  "stegosaurus": {
    "height" : 4,
    "length" : 9,
    "weight" : 2500
  }
}

আপনি তিনটি উপায়ে ডেটা অর্ডার করতে পারেন: চাইল্ড কী দ্বারা, কী দ্বারা বা মান দ্বারা। একটি মৌলিক ডাটাবেস ক্যোয়ারী এই অর্ডারিং ফাংশনগুলির একটি দিয়ে শুরু হয়, যার প্রতিটি নীচে ব্যাখ্যা করা হয়েছে।

একটি নির্দিষ্ট চাইল্ড কী দ্বারা অর্ডার করা

আপনি orderByChild() এ সেই কীটি পাস করে একটি সাধারণ চাইল্ড কী দ্বারা নোড অর্ডার করতে পারেন। উদাহরণস্বরূপ, উচ্চতা অনুসারে অর্ডার করা সমস্ত ডাইনোসর পড়তে, আপনি নিম্নলিখিতগুলি করতে পারেন:

জাভা
public static class Dinosaur {

  public int height;
  public int weight;

  public Dinosaur(int height, int weight) {
    // ...
  }

}

final DatabaseReference dinosaursRef = database.getReference("dinosaurs");
dinosaursRef.orderByChild("height").addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    Dinosaur dinosaur = dataSnapshot.getValue(Dinosaur.class);
    System.out.println(dataSnapshot.getKey() + " was " + dinosaur.height + " meters tall.");
  }

  // ...
});
Node.js
const ref = db.ref('dinosaurs');

ref.orderByChild('height').on('child_added', (snapshot) => {
  console.log(snapshot.key + ' was ' + snapshot.val().height + ' meters tall');
});
পাইথন
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('height').get()
for key, val in snapshot.items():
    print('{0} was {1} meters tall'.format(key, val))
যাও
// Dinosaur is a json-serializable type.
type Dinosaur struct {
	Height int `json:"height"`
	Width  int `json:"width"`
}

ref := client.NewRef("dinosaurs")

results, err := ref.OrderByChild("height").GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	var d Dinosaur
	if err := r.Unmarshal(&d); err != nil {
		log.Fatalln("Error unmarshaling result:", err)
	}
	fmt.Printf("%s was %d meteres tall", r.Key(), d.Height)
}

যে কোনো নোডের কাছে আমরা যে চাইল্ড কীটি অনুসন্ধান করছি সেটি null এর মান দিয়ে সাজানো হয়, যার অর্থ এটি ক্রমানুসারে প্রথমে আসবে। ডেটা কীভাবে অর্ডার করা হয় তার বিশদ বিবরণের জন্য, কীভাবে ডেটা অর্ডার করা হয় বিভাগটি দেখুন।

প্রশ্নগুলি গভীরভাবে নেস্টেড বাচ্চাদের দ্বারাও অর্ডার করা যেতে পারে, শুধুমাত্র বাচ্চাদের এক স্তর নিচে না দিয়ে। আপনার কাছে এইরকম গভীরভাবে নেস্টেড ডেটা থাকলে এটি দরকারী:

{
  "lambeosaurus": {
    "dimensions": {
      "height" : 2.1,
      "length" : 12.5,
      "weight": 5000
    }
  },
  "stegosaurus": {
    "dimensions": {
      "height" : 4,
      "length" : 9,
      "weight" : 2500
    }
  }
}

এখন উচ্চতা জিজ্ঞাসা করতে, আপনি একটি একক কী এর পরিবর্তে বস্তুর সম্পূর্ণ পথ ব্যবহার করতে পারেন:

জাভা
dinosaursRef.orderByChild("dimensions/height").addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    // ...
  }

  // ...
});
Node.js
const ref = db.ref('dinosaurs');
ref.orderByChild('dimensions/height').on('child_added', (snapshot) => {
  console.log(snapshot.key + ' was ' + snapshot.val().height + ' meters tall');
});
পাইথন
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('dimensions/height').get()
for key, val in snapshot.items():
    print('{0} was {1} meters tall'.format(key, val))
যাও
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByChild("dimensions/height").GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	var d Dinosaur
	if err := r.Unmarshal(&d); err != nil {
		log.Fatalln("Error unmarshaling result:", err)
	}
	fmt.Printf("%s was %d meteres tall", r.Key(), d.Height)
}

প্রশ্নগুলি একবারে শুধুমাত্র একটি কী দ্বারা অর্ডার করতে পারে। একই ক্যোয়ারীতে একাধিকবার orderByChild() কল করলে একটি ত্রুটি দেখা দেয়।

চাবি দ্বারা আদেশ

আপনি orderByKey() পদ্ধতি ব্যবহার করে তাদের কী দ্বারা নোড অর্ডার করতে পারেন। নিম্নলিখিত উদাহরণটি বর্ণানুক্রমিক ক্রমে সমস্ত ডাইনোসর পড়ে:

জাভা
dinosaursRef.orderByKey().addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
var ref = db.ref('dinosaurs');
ref.orderByKey().on('child_added', (snapshot) => {
  console.log(snapshot.key);
});
পাইথন
ref = db.reference('dinosaurs')
snapshot = ref.order_by_key().get()
print(snapshot)
যাও
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByKey().GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
snapshot := make([]Dinosaur, len(results))
for i, r := range results {
	var d Dinosaur
	if err := r.Unmarshal(&d); err != nil {
		log.Fatalln("Error unmarshaling result:", err)
	}
	snapshot[i] = d
}
fmt.Println(snapshot)

মান অনুযায়ী ক্রম

আপনি orderByValue() পদ্ধতি ব্যবহার করে তাদের চাইল্ড কীগুলির মান অনুসারে নোডগুলি অর্ডার করতে পারেন। ধরা যাক ডাইনোসরদের একটি ডাইনো স্পোর্টস প্রতিযোগিতা চলছে এবং আপনি নিম্নলিখিত ফর্ম্যাটে তাদের স্কোর ট্র্যাক করছেন:

{
  "scores": {
    "bruhathkayosaurus" : 55,
    "lambeosaurus" : 21,
    "linhenykus" : 80,
    "pterodactyl" : 93,
    "stegosaurus" : 5,
    "triceratops" : 22
  }
}

ডাইনোসরদের তাদের স্কোর অনুসারে সাজাতে, আপনি নিম্নলিখিত প্রশ্নটি তৈরি করতে পারেন:

জাভা
DatabaseReference scoresRef = database.getReference("scores");
scoresRef.orderByValue().addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println("The " + dataSnapshot.getKey() + " score is " + dataSnapshot.getValue());
  }

  // ...
});
Node.js
const scoresRef = db.ref('scores');
scoresRef.orderByValue().on('value', (snapshot) => {
  snapshot.forEach((data) => {
    console.log('The ' + data.key + ' dinosaur\'s score is ' + data.val());
  });
});
পাইথন
ref = db.reference('scores')
snapshot = ref.order_by_value().get()
for key, val in snapshot.items():
    print('The {0} dinosaur\'s score is {1}'.format(key, val))
যাও
ref := client.NewRef("scores")

results, err := ref.OrderByValue().GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	var score int
	if err := r.Unmarshal(&score); err != nil {
		log.Fatalln("Error unmarshaling result:", err)
	}
	fmt.Printf("The %s dinosaur's score is %d\n", r.Key(), score)
}

orderByValue() ব্যবহার করার সময় null , বুলিয়ান, স্ট্রিং এবং অবজেক্টের মানগুলি কীভাবে সাজানো হয় তার ব্যাখ্যার জন্য কীভাবে ডেটা অর্ডার করা হয় বিভাগটি দেখুন।

জটিল প্রশ্ন

এখন যেহেতু আপনার ডেটা কীভাবে অর্ডার করা হয়েছে তা পরিষ্কার হয়ে গেছে, আপনি আরও জটিল প্রশ্ন তৈরি করতে নীচে বর্ণিত সীমা বা ব্যাপ্তি পদ্ধতি ব্যবহার করতে পারেন৷

সীমিত প্রশ্ন

limitToFirst() এবং limitToLast() ক্যোয়ারীগুলি একটি প্রদত্ত কলব্যাকের জন্য সিঙ্ক করার জন্য সর্বাধিক সংখ্যক বাচ্চা সেট করতে ব্যবহৃত হয়। আপনি যদি 100-এর একটি সীমা সেট করেন, আপনি প্রাথমিকভাবে শুধুমাত্র 100টি পর্যন্ত child_added ইভেন্ট পাবেন। আপনার ডাটাবেসে 100 টিরও কম বার্তা সংরক্ষিত থাকলে, প্রতিটি বার্তার জন্য একটি child_added ইভেন্ট ফায়ার হবে। যাইহোক, যদি আপনার কাছে 100 টির বেশি বার্তা থাকে, আপনি সেই 100 টির জন্য শুধুমাত্র একটি child_added ইভেন্ট পাবেন৷ যদি আপনি limitToFirst() ব্যবহার করেন তাহলে এই প্রথম 100টি অর্ডার করা বার্তা অথবা আপনি যদি limitToLast() ব্যবহার করেন তাহলে শেষ 100টি অর্ডার করা বার্তা। আইটেমগুলি পরিবর্তিত হওয়ার সাথে সাথে, আপনি যে আইটেমগুলির জন্য ক্যোয়ারী প্রবেশ করেন তাদের জন্য child_added ইভেন্টগুলি এবং আইটেমগুলি ছেড়ে যাওয়া আইটেমগুলির জন্য child_removed ইভেন্টগুলি পাবেন, যাতে মোট সংখ্যা 100-এ থাকে৷

ডাইনোসর ফ্যাক্ট ডাটাবেস এবং orderByChild() ব্যবহার করে, আপনি দুটি ভারী ডাইনোসর খুঁজে পেতে পারেন:

জাভা
dinosaursRef.orderByChild("weight").limitToLast(2).addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
const ref = db.ref('dinosaurs');
ref.orderByChild('weight').limitToLast(2).on('child_added', (snapshot) => {
  console.log(snapshot.key);
});
পাইথন
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('weight').limit_to_last(2).get()
for key in snapshot:
    print(key)
যাও
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByChild("weight").LimitToLast(2).GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	fmt.Println(r.Key())
}

child_added কলব্যাকটি ঠিক দুইবার ট্রিগার হয়, যদি না ডাটাবেসে দুটির কম ডাইনোসর সংরক্ষিত থাকে। ডাটাবেসে যুক্ত হওয়া প্রতিটি নতুন, ভারী ডাইনোসরের জন্য এটি বরখাস্ত করা হবে। পাইথনে, ক্যোয়ারী সরাসরি দুটি ভারী ডাইনোসর সম্বলিত একটি OrderedDict প্রদান করে।

একইভাবে, আপনি limitToFirst() ব্যবহার করে দুটি ছোট ডাইনোসর খুঁজে পেতে পারেন:

জাভা
dinosaursRef.orderByChild("weight").limitToFirst(2).addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
const ref = db.ref('dinosaurs');
ref.orderByChild('height').limitToFirst(2).on('child_added', (snapshot) => {
  console.log(snapshot.key);
});
পাইথন
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('height').limit_to_first(2).get()
for key in snapshot:
    print(key)
যাও
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByChild("height").LimitToFirst(2).GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	fmt.Println(r.Key())
}

child_added কলব্যাকটি ঠিক দুইবার ট্রিগার হয়, যদি না ডাটাবেসে দুটির কম ডাইনোসর সংরক্ষিত থাকে। ডাটাবেস থেকে প্রথম দুটি ডাইনোসরের একটি মুছে ফেলা হলে এটি আবার বরখাস্ত হবে, কারণ একটি নতুন ডাইনোসর এখন দ্বিতীয় ছোট হবে। Python-এ, ক্যোয়ারী সরাসরি একটি OrderedDict ফেরত দেয় যেখানে সবচেয়ে ছোট ডাইনোসর রয়েছে।

আপনি orderByValue() দিয়ে সীমা প্রশ্নগুলিও পরিচালনা করতে পারেন। আপনি যদি শীর্ষ 3টি সর্বোচ্চ স্কোরিং ডাইনো স্পোর্টস ডাইনোসরগুলির সাথে একটি লিডারবোর্ড তৈরি করতে চান তবে আপনি নিম্নলিখিতগুলি করতে পারেন:

জাভা
scoresRef.orderByValue().limitToFirst(3).addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println("The " + dataSnapshot.getKey() + " score is " + dataSnapshot.getValue());
  }

  // ...
});
Node.js
const scoresRef = db.ref('scores');
scoresRef.orderByValue().limitToLast(3).on('value', (snapshot)  =>{
  snapshot.forEach((data) => {
    console.log('The ' + data.key + ' dinosaur\'s score is ' + data.val());
  });
});
পাইথন
scores_ref = db.reference('scores')
snapshot = scores_ref.order_by_value().limit_to_last(3).get()
for key, val in snapshot.items():
    print('The {0} dinosaur\'s score is {1}'.format(key, val))
যাও
ref := client.NewRef("scores")

results, err := ref.OrderByValue().LimitToLast(3).GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	var score int
	if err := r.Unmarshal(&score); err != nil {
		log.Fatalln("Error unmarshaling result:", err)
	}
	fmt.Printf("The %s dinosaur's score is %d\n", r.Key(), score)
}

পরিসীমা প্রশ্ন

startAt() , endAt() , এবং equalTo() ব্যবহার করে আপনি আপনার প্রশ্নের জন্য নির্বিচারে শুরু এবং শেষ বিন্দু নির্বাচন করতে পারবেন। উদাহরণস্বরূপ, আপনি যদি কমপক্ষে তিন মিটার লম্বা সমস্ত ডাইনোসর খুঁজে পেতে চান তবে আপনি orderByChild() এবং startAt() একত্রিত করতে পারেন :

জাভা
dinosaursRef.orderByChild("height").startAt(3).addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
const ref = db.ref('dinosaurs');
ref.orderByChild('height').startAt(3).on('child_added', (snapshot) => {
  console.log(snapshot.key);
});
পাইথন
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('height').start_at(3).get()
for key in snapshot:
    print(key)
যাও
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByChild("height").StartAt(3).GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	fmt.Println(r.Key())
}

আপনি endAt() ব্যবহার করতে পারেন এমন সমস্ত ডাইনোসর খুঁজে পেতে যাদের নাম লেক্সিকোগ্রাফিকভাবে Pterodactyl এর আগে আসে:

জাভা
dinosaursRef.orderByKey().endAt("pterodactyl").addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
const ref = db.ref('dinosaurs');
ref.orderByKey().endAt('pterodactyl').on('child_added', (snapshot) => {
  console.log(snapshot.key);
});
পাইথন
ref = db.reference('dinosaurs')
snapshot = ref.order_by_key().end_at('pterodactyl').get()
for key in snapshot:
    print(key)
যাও
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByKey().EndAt("pterodactyl").GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	fmt.Println(r.Key())
}

আপনি আপনার প্রশ্নের উভয় প্রান্ত সীমাবদ্ধ করতে startAt() এবং endAt() একত্রিত করতে পারেন। নিম্নলিখিত উদাহরণে এমন সমস্ত ডাইনোসর পাওয়া যায় যাদের নাম "b" অক্ষর দিয়ে শুরু হয়:

জাভা
dinosaursRef.orderByKey().startAt("b").endAt("b\uf8ff").addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
var ref = db.ref('dinosaurs');
ref.orderByKey().startAt('b').endAt('b\uf8ff').on('child_added', (snapshot) => {
  console.log(snapshot.key);
});
পাইথন
ref = db.reference('dinosaurs')
snapshot = ref.order_by_key().start_at('b').end_at(u'b\uf8ff').get()
for key in snapshot:
    print(key)
যাও
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByKey().StartAt("b").EndAt("b\uf8ff").GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	fmt.Println(r.Key())
}

equalTo() পদ্ধতি আপনাকে সঠিক মিলের উপর ভিত্তি করে ফিল্টার করতে দেয়। অন্যান্য পরিসরের প্রশ্নের মতোই, এটি প্রতিটি মিলে যাওয়া চাইল্ড নোডের জন্য ফায়ার করবে। উদাহরণস্বরূপ, আপনি 25 মিটার লম্বা সমস্ত ডাইনোসর খুঁজে পেতে নিম্নলিখিত প্রশ্নটি ব্যবহার করতে পারেন:

জাভা
dinosaursRef.orderByChild("height").equalTo(25).addChildEventListener(new ChildEventListener() {
  @Override
  public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
    System.out.println(dataSnapshot.getKey());
  }

  // ...
});
Node.js
const ref = db.ref('dinosaurs');
ref.orderByChild('height').equalTo(25).on('child_added', (snapshot) => {
  console.log(snapshot.key);
});
পাইথন
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('height').equal_to(25).get()
for key in snapshot:
    print(key)
যাও
ref := client.NewRef("dinosaurs")

results, err := ref.OrderByChild("height").EqualTo(25).GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
for _, r := range results {
	fmt.Println(r.Key())
}

আপনার ডেটা পেজিনেট করার প্রয়োজন হলে রেঞ্জ কোয়েরিগুলিও কার্যকর।

এটা সব একসাথে নির্বাণ

আপনি জটিল প্রশ্ন তৈরি করতে এই সমস্ত কৌশল একত্রিত করতে পারেন। উদাহরণস্বরূপ, আপনি ডাইনোসরের নাম খুঁজে পেতে পারেন যা স্টেগোসরাসের চেয়ে ছোট:

জাভা
dinosaursRef.child("stegosaurus").child("height").addValueEventListener(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot stegoHeightSnapshot) {
    Integer favoriteDinoHeight = stegoHeightSnapshot.getValue(Integer.class);
    Query query = dinosaursRef.orderByChild("height").endAt(favoriteDinoHeight).limitToLast(2);
    query.addValueEventListener(new ValueEventListener() {
      @Override
      public void onDataChange(DataSnapshot dataSnapshot) {
        // Data is ordered by increasing height, so we want the first entry
        DataSnapshot firstChild = dataSnapshot.getChildren().iterator().next();
        System.out.println("The dinosaur just shorter than the stegosaurus is: " + firstChild.getKey());
      }

      @Override
      public void onCancelled(DatabaseError databaseError) {
        // ...
      }
    });
  }

  @Override
  public void onCancelled(DatabaseError databaseError) {
    // ...
  }
});
Node.js
  const ref = db.ref('dinosaurs');
  ref.child('stegosaurus').child('height').on('value', (stegosaurusHeightSnapshot) => {
    const favoriteDinoHeight = stegosaurusHeightSnapshot.val();

    const queryRef = ref.orderByChild('height').endAt(favoriteDinoHeight).limitToLast(2);
    queryRef.on('value', (querySnapshot) => {
      if (querySnapshot.numChildren() === 2) {
        // Data is ordered by increasing height, so we want the first entry
        querySnapshot.forEach((dinoSnapshot) => {
          console.log('The dinosaur just shorter than the stegasaurus is ' + dinoSnapshot.key);

          // Returning true means that we will only loop through the forEach() one time
          return true;
        });
      } else {
        console.log('The stegosaurus is the shortest dino');
      }
    });
});
পাইথন
ref = db.reference('dinosaurs')
favotire_dino_height = ref.child('stegosaurus').child('height').get()
query = ref.order_by_child('height').end_at(favotire_dino_height).limit_to_last(2)
snapshot = query.get()
if len(snapshot) == 2:
    # Data is ordered by increasing height, so we want the first entry.
    # Second entry is stegosarus.
    for key in snapshot:
        print('The dinosaur just shorter than the stegosaurus is {0}'.format(key))
        return
else:
    print('The stegosaurus is the shortest dino')
যাও
ref := client.NewRef("dinosaurs")

var favDinoHeight int
if err := ref.Child("stegosaurus").Child("height").Get(ctx, &favDinoHeight); err != nil {
	log.Fatalln("Error querying database:", err)
}

query := ref.OrderByChild("height").EndAt(favDinoHeight).LimitToLast(2)
results, err := query.GetOrdered(ctx)
if err != nil {
	log.Fatalln("Error querying database:", err)
}
if len(results) == 2 {
	// Data is ordered by increasing height, so we want the first entry.
	// Second entry is stegosarus.
	fmt.Printf("The dinosaur just shorter than the stegosaurus is %s\n", results[0].Key())
} else {
	fmt.Println("The stegosaurus is the shortest dino")
}

কিভাবে ডেটা অর্ডার করা হয়

এই বিভাগটি ব্যাখ্যা করে যে চারটি অর্ডারিং ফাংশনের প্রতিটি ব্যবহার করার সময় আপনার ডেটা কীভাবে অর্ডার করা হয়।

অর্ডার বাই চাইল্ড

orderByChild() ব্যবহার করার সময়, নির্দিষ্ট চাইল্ড কী ধারণ করে এমন ডেটা নিম্নরূপ সাজানো হয়:

  1. নির্দিষ্ট চাইল্ড কী-এর জন্য একটি null মান সহ শিশুরা প্রথমে আসে।
  2. নির্দিষ্ট চাইল্ড কী-এর জন্য false এর মান সহ শিশু পরবর্তী আসে। যদি একাধিক শিশুর false মান থাকে, তাহলে সেগুলোকে কী দ্বারা অভিধানিকভাবে সাজানো হয়।
  3. নির্দিষ্ট চাইল্ড কী-এর জন্য true মান সহ শিশু পরবর্তী আসে। যদি একাধিক বাচ্চাদের true মান থাকে, তবে সেগুলি কী দ্বারা অভিধানিকভাবে সাজানো হয়।
  4. একটি সাংখ্যিক মান সহ বাচ্চারা পরবর্তীতে আসে, আরোহী ক্রমে সাজানো হয়। যদি নির্দিষ্ট চাইল্ড নোডের জন্য একাধিক বাচ্চার সংখ্যাগত মান একই থাকে, তবে সেগুলি কী দ্বারা বাছাই করা হয়।
  5. স্ট্রিংগুলি সংখ্যার পরে আসে এবং ঊর্ধ্বক্রম অনুসারে অভিধানিকভাবে সাজানো হয়। যদি নির্দিষ্ট চাইল্ড নোডের জন্য একাধিক বাচ্চার মান একই থাকে, তবে তাদের কী দ্বারা অভিধানিকভাবে আদেশ করা হয়।
  6. অবজেক্ট সবশেষে আসে, এবং ঊর্ধ্বক্রম অনুসারে কী দ্বারা অভিধানিকভাবে সাজানো হয়।

orderByKey

আপনার ডেটা সাজানোর জন্য orderByKey() ব্যবহার করার সময়, নিচের মত কী দ্বারা ডেটা ঊর্ধ্বমুখী ক্রমে ফেরত দেওয়া হয়। মনে রাখবেন কী শুধুমাত্র স্ট্রিং হতে পারে।

  1. 32-বিট পূর্ণসংখ্যা হিসাবে পার্স করা যেতে পারে এমন একটি কী সহ বাচ্চারা প্রথমে আসে, আরোহী ক্রমে সাজানো হয়।
  2. একটি স্ট্রিং মান সহ বাচ্চারা তাদের কী হিসাবে পরবর্তী আসে, লেক্সিকোগ্রাফিকভাবে আরোহী ক্রমে সাজানো হয়।

orderByValue

orderByValue() ব্যবহার করার সময়, বাচ্চাদের তাদের মান অনুসারে অর্ডার করা হয়। অর্ডার করার মানদণ্ড orderByChild() এর মতোই, নোডের মানটি একটি নির্দিষ্ট চাইল্ড কী-এর মানের পরিবর্তে ব্যবহার করা ছাড়া।