Buka konsol

Mengambil Data

Dokumen ini membahas dasar-dasar pengambilan data database, bagaimana data diurutkan, dan cara melakukan kueri sederhana pada data. Pengambilan data di Admin SDK diterapkan dengan cara yang sedikit berbeda di bahasa pemrograman yang berbeda.

  1. Listener asinkron: Data yang disimpan di Firebase Realtime Database diambil dengan melampirkan listener asinkron ke referensi database. Listener ini dipicu sekali untuk status awal data dan dipicu kembali setiap kali data berubah. Listener peristiwa mungkin menerima jenis peristiwa yang berbeda. Cara pengambilan data ini didukung di Admin SDK Java, Node.js, dan Python.
  2. Pemblokiran pembacaan: Data yang tersimpan dalam Firebase Realtime Database diambil dengan meminta metode pemblokiran pada referensi database yang menampilkan data yang tersimpan pada referensi. Masing-masing pemanggilan metode adalah operasi sekali pakai. Itu berarti SDK tidak mendaftarkan callback yang mendeteksi update data berikutnya. Model pengambilan data ini didukung di Python dan Go Admin SDK.

Memulai

Perhatikan kembali contoh blogging dari artikel sebelumnya untuk memahami cara membaca data dari database Firebase. Ingatlah bahwa entri blog dalam aplikasi contoh disimpan di URL database https://docs-examples.firebaseio.com/server/saving-data/fireblog/posts. Untuk membaca data entri, Anda bisa melakukan hal berikut:

Java
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
// Import Admin SDK
var admin = require("firebase-admin");

// Get a database reference to our posts
var db = admin.database();
var ref = db.ref("server/saving-data/fireblog/posts");

// Attach an asynchronous callback to read the data at our posts reference
ref.on("value", function(snapshot) {
  console.log(snapshot.val());
}, function (errorObject) {
  console.log("The read failed: " + errorObject.code);
});
Python
# 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())
Go

// 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)
}

Jika Anda menjalankan kode di atas, Anda akan melihat objek yang berisi semua entri Anda yang dibuat lognya ke konsol. Pada kasus Node.js dan Java, fungsi listener ini akan dipanggil setiap kali ada data baru ditambahkan ke referensi database dan Anda tidak perlu menulis kode tambahan untuk menjalankannya.

Di Java dan Node.js, fungsi callback menerima DataSnapshot, yang merupakan snapshot dari data. Snapshot adalah foto dari data pada referensi database tertentu pada suatu titik waktu. Memanggil val() / getValue() pada snapshot akan menampilkan perwakilan objek spesifik bahasa dari data tersebut. Jika tidak ada data di lokasi referensi, nilai snapshot akan menjadi null. Metode get() dengan Python menampilkan perwakilan Python dari data tersebut secara langsung. Fungsi Get() dalam Go memecah susunan data ini ke dalam struktur data tertentu.

Perhatikan bahwa kita menggunakan jenis peristiwa value pada contoh di atas yang akan membaca seluruh isi referensi database Firebase, meskipun hanya ada satu bagian data yang berubah. value adalah salah satu dari lima jenis peristiwa berbeda yang tercantum di bawah ini yang bisa Anda gunakan untuk membaca data dari database.

Jenis Peristiwa Baca di Java dan Node.js

Nilai

Peristiwa value digunakan untuk membaca snapshot statis konten pada lokasi database tertentu ketika peristiwa baca terjadi. Itu terpicu sekali saat data berada di kondisi awal data dan terpicu lagi setiap kali data berubah. Callback peristiwa diberikan snapshot yang berisi semua data di lokasi tersebut, termasuk data turunan. Pada contoh kode di atas, value menampilkan semua entri blog di aplikasi Anda. Setiap kali entri blog baru ditambahkan, fungsi callback akan menampilkan semua postingan.

Child Added

Peristiwa child_added biasanya digunakan ketika mengambil daftar item dari database. Tidak seperti value yang menampilkan seluruh konten lokasi, child_added terpicu 1 kali untuk setiap turunan yang ada dan terpicu lagi setiap kali ada turunan baru yang ditambahkan ke lokasi yang ditetapkan. Callback peristiwa diberikan snapshot yang berisi data turunan baru. Demi kemudahan pengurutan, ini juga akan meneruskan argumen kedua yang berisi kunci dari turunan sebelumnya.

Jika Anda ingin hanya mengambil data pada masing-masing entri baru yang ditambahkan ke aplikasi blogging Anda, Anda bisa menggunakan child_added:

Java
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", function(snapshot, prevChildKey) {
  var newPost = snapshot.val();
  console.log("Author: " + newPost.author);
  console.log("Title: " + newPost.title);
  console.log("Previous Post ID: " + prevChildKey);
});

Dalam contoh ini, snapshot akan berisi sebuah objek dengan entri blog individu. Karena SDK mengonversi entri menjadi objek dengan mengambil data nilainya, Anda memiliki akses ke properti penulis dan judul entri dengan memanggil author untuk penulis dan title untuk judul. Anda juga mempunyai akses ke ID entri sebelumnya dari argumen prevChildKey kedua.

Child Changed

Peristiwa child_changed terpicu setiap kali node turunan dimodifikasi. Ini juga termasuk setiap perubahan pada turunan node turunan. Ini biasanya digunakan bersama dengan child_added dan child_removed untuk merespons perubahan pada daftar item. Snapshot yang diteruskan ke callback peristiwa berisi data yang telah diupdate untuk turunan tersebut.

Anda bisa menggunakan child_changed untuk membaca data yang telah diupdate pada entri blog ketika entri blog tersebut diedit:

Java
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", function(snapshot) {
  var changedPost = snapshot.val();
  console.log("The updated post title is " + changedPost.title);
});

Child Removed

Peristiwa child_removed dipicu ketika data turunan langsung dihapus. Ini biasanya digunakan bersama dengan child_added dan child_changed. Snapshot yang diteruskan ke callback peristiwa berisi data untuk turunan yang dihapus.

Dalam contoh blog, Anda dapat menggunakan child_removed untuk membuat log notifikasi di konsol tentang entri yang dihapus:

Java
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
var ref = db.ref("server/saving-data/fireblog/posts");

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

Child Moved

Peristiwa child_moved digunakan ketika menangani data yang diurutkan, dan akan dibahas pada bagian berikutnya.

Jaminan Peristiwa

Database Firebase membuat beberapa jaminan penting mengenai peristiwa:

Jaminan Peristiwa Database
Peristiwa akan selalu dipicu ketika kondisi lokal berubah.
Peristiwa akan selalu mencerminkan keadaan yang benar dari data, bahkan ketika operasi atau waktu lokal menyebabkan perbedaan sementara, misalnya hilangnya koneksi jaringan untuk sementara.
Menulis dari klien tunggal akan selalu ditulis ke server dan disiarkan ke pengguna lain secara berurutan.
Peristiwa nilai selalu dipicu terakhir dan dijamin berisi update dari setiap peristiwa lainnya yang terjadi sebelum snapshot diambil.

Karena peristiwa nilai selalu dipicu terakhir, contoh berikut akan selalu bekerja:

Java
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
var count = 0;

ref.on("child_added", function(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", function(snap) {
  console.log("initial data loaded!", snap.numChildren() === count);
});

Melepaskan Callback

Callback dihapus dengan menetapkan tipe peristiwa dan fungsi callback yang akan dihapus, seperti berikut ini:

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

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

Jika Anda meneruskan konteks lingkup ke on(), konteks tersebut harus diteruskan saat melepaskan callback:

Java
// Not applicable for Java
Node.js
ref.off("value", originalCallback, this);

Jika ingin menghapus semua callback di suatu lokasi, Anda bisa melakukan hal berikut:

Java
// 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();

Membaca Data Sekali

Dalam beberapa kasus, mungkin akan lebih baik jika callback dipanggil sekali lalu segera dihapus. Kami telah membuat fungsi helper untuk memudahkan hal ini:

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

  @Override
  public void onCancelled(DatabaseError databaseError) {
    // ...
  }
});
Node.js
ref.once("value", function(data) {
  // do some stuff once
});
Python
# 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())
Go
// 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)
}

Mengkueri Data

Dengan kueri database Firebase, Anda bisa mengambil data secara selektif berdasarkan berbagai macam faktor. Untuk membuat kueri dalam database, mulailah dengan menentukan metode pengurutan data yang Anda inginkan dengan menggunakan salah satu fungsi pengurutan: orderByChild(), orderByKey(), atau orderByValue(). Kemudian, Anda bisa mengombinasikan metode ini dengan 5 metode lainnya untuk melakukan kueri yang kompleks: limitToFirst(), limitToLast(), startAt(), endAt(), dan equalTo().

Karena kami semua di Firebase suka dinosaurus, kami akan menggunakan cuplikan dari contoh database fakta dinosaurus untuk menunjukkan bagaimana Anda bisa mengkueri data di database Firebase:

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

Anda dapat mengurutkan data dengan 3 cara: berdasarkan kunci turunan, berdasarkan kunci, atau berdasarkan nilai. Kueri database dasar dimulai dengan salah satu fungsi pengurutan yang masing-masing akan dijelaskan di bawah ini.

Mengurutkan berdasarkan kunci turunan yang telah ditentukan

Anda bisa mengurutkan node dengan kunci turunan umum dengan meneruskan kunci tersebut ke orderByChild(). Misalnya, untuk membaca semua dinosaurus yang diurutkan berdasarkan tinggi, Anda bisa melakukan hal berikut:

Java
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
var db = firebaseAdmin.database();
var ref = db.ref("dinosaurs");
ref.orderByChild("height").on("child_added", function(snapshot) {
  console.log(snapshot.key + " was " + snapshot.val().height + " meters tall");
});
Python
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))
Go

// 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)
}

Setiap node yang tidak memiliki kunci turunan sesuai dengan kueri akan diurutkan dengan nilai null, yang membuatnya akan muncul di urutan pertama. Untuk detail tentang cara data diurutkan, lihat bagian Cara Data Diurutkan.

Kueri juga bisa diurutkan dengan turunan bertingkat yang dalam, bukan oleh turunan yang hanya 1 level ke bawah. Hal ini berguna jika Anda memiliki data bertingkat yang dalam seperti ini:

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

Untuk mengkueri tinggi, kita menggunakan lokasi lengkap ke objek, bukan kunci tunggal:

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

  // ...
});
Node.js
var ref = db.ref("dinosaurs");
ref.orderByChild("dimensions/height").on("child_added", function(snapshot) {
  console.log(snapshot.key + " was " + snapshot.val().height + " meters tall");
});
Python
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))
Go
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)
}

Kueri hanya bisa mengurutkan dengan 1 kunci pada satu waktu. Memanggil orderByChild() beberapa kali dalam kueri yang sama akan memunculkan error.

Mengurutkan berdasarkan kunci

Anda juga dapat mengurutkan node dengan kuncinya menggunakan metode orderByKey(). Contoh berikut membaca semua dinosaurus sesuai urutan abjad:

Java
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", function(snapshot) {
  console.log(snapshot.key);
});
Python
ref = db.reference('dinosaurs')
snapshot = ref.order_by_key().get()
print(snapshot)
Go
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)

Mengurutkan berdasarkan nilai

Anda bisa mengurutkan node berdasarkan nilai kunci turunannya menggunakan metode orderByValue(). Anggap dinosaurus sedang mengadakan kompetisi olahraga dino dan Anda mengikuti perkembangan skornya dalam format berikut:

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

Untuk mengurutkan dinosaurus berdasarkan skor yang diraihnya, Anda bisa membuat kueri berikut:

Java
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
var scoresRef = db.ref("scores");
scoresRef.orderByValue().on("value", function(snapshot) {
  snapshot.forEach(function(data) {
    console.log("The " + data.key + " dinosaur's score is " + data.val());
  });
});
Python
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))
Go
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)
}

Lihat bagian Metode Pengurutan Data untuk mendapatkan penjelasan tentang pengurutan nilai null, boolean, string, dan objek jika orderByValue() digunakan.

Kueri Kompleks

Setelah memahami pengurutan data, Anda dapat menggunakan metode batas atau rentang yang dijelaskan di bawah ini untuk membuat kueri yang lebih kompleks.

Kueri Batas

Kueri limitToFirst() dan limitToLast() digunakan untuk menyetel jumlah maksimum turunan yang disinkronkan untuk callback tertentu. Jika batasnya kita tentukan sebanyak 100, awalnya Anda hanya akan menerima hingga 100 peristiwa child_added. Jika Anda memiliki kurang dari 100 pesan yang tersimpan dalam database, peristiwa child_added akan diaktifkan untuk setiap pesan. Akan tetapi, jika Anda memiliki lebih dari 100 pesan, Anda hanya akan menerima peristiwa child_added untuk 100 pesan tersebut. Ini akan menjadi 100 pesan urutan pertama jika Anda menggunakan limitToFirst() atau 100 pesan urutan terakhir jika Anda menggunakan limitToLast(). Saat item berubah, Anda akan menerima peristiwa child_added untuk item yang masuk ke kueri dan peristiwa child_removed untuk item yang keluar, sehingga jumlah totalnya tetap 100.

Dengan menggunakan database fakta dinosaurus dan orderByChild(), Anda dapat menemukan 2 dinosaurus terberat:

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

  // ...
});
Node.js
var ref = db.ref("dinosaurs");
ref.orderByChild("weight").limitToLast(2).on("child_added", function(snapshot) {
  console.log(snapshot.key);
});
Python
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('weight').limit_to_last(2).get()
for key in snapshot:
    print(key)
Go
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())
}

Callback child_added akan terpicu tepat 2 kali, kecuali jika jumlah dinosaurus di database kurang dari 2. Itu juga akan terpicu dengan setiap dinosaurus baru yang lebih berat yang ditambahkan ke database. Dalam Python, kuerinya secara langsung menampilkan OrderedDict berisi 2 dinosaurus terberat.

Demikian pula, Anda bisa menemukan 2 dinosaurus terpendek dengan menggunakan limitToFirst():

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

  // ...
});
Node.js
var ref = db.ref("dinosaurs");
ref.orderByChild("height").limitToFirst(2).on("child_added", function(snapshot) {
  console.log(snapshot.key);
});
Python
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('height').limit_to_first(2).get()
for key in snapshot:
    print(key)
Go
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())
}

Callback child_added akan terpicu tepat 2 kali, kecuali jika jumlah dinosaurus di database kurang dari 2. Callback ini juga akan terpicu lagi jika salah satu dari kedua dinosaurus pertama dihapus dari database, sehingga menyebabkan adanya dinosaurus baru yang menjadi terpendek kedua. Dalam Python, kuerinya secara langsung menampilkan OrderedDict yang berisi dinosaurus terpendek.

Anda juga bisa melakukan kueri batas dengan orderByValue(). Jika Anda ingin membuat papan peringkat dinosaurus yang masuk 3 besar dengan skor tertinggi di olahraga dino, kita bisa melakukan hal berikut:

Java
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
var scoresRef = db.ref("scores");
scoresRef.orderByValue().limitToLast(3).on("value", function(snapshot) {
  snapshot.forEach(function(data) {
    console.log("The " + data.key + " dinosaur's score is " + data.val());
  });
});
Python
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))
Go
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)
}

Kueri Rentang

Dengan menggunakan startAt(), endAt(), dan equalTo() Anda bisa memilih poin mulai dan poin akhir untuk kueri Anda. Misalnya, jika Anda ingin menemukan semua dinosaurus setinggi 3 meter, Anda dapat menggabungkan orderByChild() dan startAt():

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

  // ...
});
Node.js
  var ref = db.ref("dinosaurs");
  ref.orderByChild("height").startAt(3).on("child_added", function(snapshot) {
    console.log(snapshot.key);
  });
Python
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('height').start_at(3).get()
for key in snapshot:
    print(key)
Go
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())
}

Anda bisa menggunakan endAt() untuk menemukan semua dinosaurus yang namanya muncul sebelum Pterodactyl secara leksikografis:

Java
dinosaursRef.orderByKey().endAt("pterodactyl").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().endAt("pterodactyl").on("child_added", function(snapshot) {
  console.log(snapshot.key);
});
Python
ref = db.reference('dinosaurs')
snapshot = ref.order_by_key().end_at('pterodactyl').get()
for key in snapshot:
    print(key)
Go
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())
}

Anda dapat menggabungkan startAt() dan endAt() untuk membatasi kedua ujung kueri Anda. Contoh berikut menemukan semua dinosaurus yang namanya dimulai dengan huruf "b":

Java
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", function(snapshot) {
  console.log(snapshot.key);
});
Python
ref = db.reference('dinosaurs')
snapshot = ref.order_by_key().start_at('b').end_at(u'b\uf8ff').get()
for key in snapshot:
    print(key)
Go
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())
}

Metode equalTo() memungkinkan Anda melakukan filter berdasarkan pencocokan persis. Seperti halnya dengan kueri rentang lainnya, pemicuan akan terjadi untuk setiap node turunan yang cocok. Misalnya, Anda bisa menggunakan kueri berikut untuk menemukan semua dinosaurus yang tingginya 25 meter:

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

  // ...
});
Node.js
var ref = db.ref("dinosaurs");
ref.orderByChild("height").equalTo(25).on("child_added", function(snapshot) {
  console.log(snapshot.key);
});
Python
ref = db.reference('dinosaurs')
snapshot = ref.order_by_child('height').equal_to(25).get()
for key in snapshot:
    print(key)
Go
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())
}

Kueri rentang juga berguna ketika Anda perlu memberi nomor pada data.

Menggabungkan semuanya

Anda bisa menggabungkan semua teknik ini untuk membuat kueri yang kompleks. Misalnya, Anda bisa menemukan nama dinosaurus yang lebih pendek dari Stegosaurus:

Java
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
var ref = db.ref("dinosaurs");
ref.child("stegosaurus").child("height").on("value", function(stegosaurusHeightSnapshot) {
  var favoriteDinoHeight = stegosaurusHeightSnapshot.val();

  var queryRef = ref.orderByChild("height").endAt(favoriteDinoHeight).limitToLast(2)
  queryRef.on("value", function(querySnapshot) {
    if (querySnapshot.numChildren() === 2) {
      // Data is ordered by increasing height, so we want the first entry
      querySnapshot.forEach(function(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");
    }
  });
});
Python
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')
Go
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")
}

Metode Pengurutan Data

Bagian ini menjelaskan bagaimana data Anda diurutkan ketika menggunakan 4 fungsi pengurutan yang berbeda.

orderByChild

Ketika menggunakan orderByChild(), data yang berisi kunci turunan yang ditentukan diurutkan sebagai berikut:

  1. Turunan yang memiliki nilai null untuk kunci turunan yang ditentukan akan muncul pertama.
  2. Turunan yang memiliki nilai false untuk kunci turunan yang ditentukan akan muncul berikutnya. Jika beberapa turunan memiliki nilai false, turunan tersebut akan diurutkan secara leksikografis berdasarkan kunci.
  3. Turunan yang memiliki nilai true untuk kunci turunan yang ditentukan akan muncul berikutnya. Jika beberapa turunan memiliki nilai true, turunan tersebut akan diurutkan secara leksikografis berdasarkan kunci.
  4. Turunan dengan nilai numerik akan muncul berikutnya, diurutkan dalam urutan menaik. Jika beberapa turunan memiliki nilai numerik yang sama untuk node turunan yang ditentukan, turunan tersebut akan diurutkan berdasarkan kunci.
  5. String muncul setelah angka, dan diurutkan secara leksikografis dalam urutan menaik. Jika beberapa turunan memiliki nilai yang sama untuk node turunan yang ditentukan, nilai tersebut akan diurutkan secara leksikografis berdasarkan kunci.
  6. Objek muncul terakhir, dan diurutkan secara leksikografis berdasarkan kunci dalam urutan menaik.

orderByKey

Ketika Anda menggunakan orderByKey() untuk mengurutkan data, data akan ditampilkan dalam urutan menaik berdasarkan kunci. Perlu diingat bahwa kunci hanya bisa berupa string.

  1. Turunan dengan kunci yang bisa diurai sebagai bilangan bulat 32-bit berada di urutan atas, diurutkan dalam urutan menaik.
  2. Turunan dengan nilai string sebagai kuncinya berada di urutan berikutnya, diurutkan secara leksikografis dalam urutan menaik.

orderByValue

Ketika menggunakan orderByValue(), turunan akan diurutkan berdasarkan nilainya. Kriteria urutan sama seperti di orderByChild(), namun yang digunakan adalah nilai node, bukan nilai kunci turunan yang ditentukan.