Veri Alma

Bu dokümanda, veritabanı verilerinin alınması, verilerin nasıl sıralandığı ve verilerle ilgili basit sorguların nasıl gerçekleştirileceğiyle ilgili temel bilgiler ele alınmaktadır. Yönetici SDK'sında veri alma işlemi, farklı programlama dillerinde biraz farklı şekilde uygulanır.

  1. Eşzamansız dinleyiciler: Firebase Realtime Database içinde depolanan veriler, bir veritabanı referansına eşzamansız dinleyici eklenerek alınır. Dinleyici, verilerin ilk durumu için bir kez ve veriler değiştiğinde tekrar tetiklenir. Bir etkinlik dinleyicisi çeşitli farklı etkinlik türleri alabilir. Bu veri alma modu Java, Node.js ve Python Yönetici SDK'larında desteklenir.
  2. Okumaların engellenmesi: Firebase Realtime Database içinde depolanan veriler, veritabanı referansında bir engelleme yöntemi çağırılarak alınır. Bu yöntem, referansta depolanan verileri döndürür. Her yöntem çağrısı tek seferlik bir işlemdir. Bu, SDK'nın sonraki veri güncellemelerini dinleyen geri çağırma işlevleri kaydetmediği anlamına gelir. Bu veri alma modeli, Python ve Go Yönetici SDK'larında desteklenir.

Başlarken

Firebase veritabanından verilerin nasıl okunacağını anlamak için önceki makaledeki blog örneğini tekrar inceleyelim. Örnek uygulamadaki blog yayınlarının https://docs-examples.firebaseio.com/server/saving-data/fireblog/posts.json veritabanı URL'sinde depolandığını unutmayın. Yayın verilerinizi okumak için aşağıdakileri yapabilirsiniz:

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

Yukarıdaki kodu çalıştırırsanız konsola kaydedilen tüm yayınlarınızı içeren bir nesne görürsünüz. Node.js ve Java'da, dinleyici işlevi veritabanı referanslarınıza her yeni veri eklendiğinde çağrılır ve bunun gerçekleşmesi için ek kod yazmanıza gerek yoktur.

Java ve Node.js'de geri çağırma işlevi, verilerin anlık görüntüsünü içeren bir DataSnapshot alır. Anlık görüntü, belirli bir veritabanı referansında belirli bir zamandaki verilerin resmidir. Bir anlık görüntüde val() / getValue() çağrısı yapıldığında, verilerin dile özgü nesne temsili döndürülür. Referansın konumunda veri yoksa anlık görüntünün değeri null olur. Python'daki get() yöntemi, verilerin doğrudan Python temsilini döndürür. Go'daki Get() işlevi, verileri belirli bir veri yapısına yerleştirir.

Yukarıdaki örnekte, yalnızca bir veri değişse bile bir Firebase veritabanı referansının tüm içeriğini okuyan value etkinlik türünü kullandığımıza dikkat edin. value, veritabanındaki verileri okumak için kullanabileceğiniz, aşağıda listelenen beş farklı etkinlik türünden biridir.

Java ve Node.js'de etkinlik türlerini okuma

Değer

value etkinliği, belirli bir veritabanı yolundaki içeriklerin okuma etkinliği sırasındaki statik anlık görüntüsünü okumak için kullanılır. İlk verilerle bir kez ve veriler her değiştiğinde tekrar tetiklenir. Etkinlik geri çağırma işlevine, alt veriler dahil olmak üzere bu konumdaki tüm verileri içeren bir anlık görüntü iletilir. Yukarıdaki kod örneğinde value, uygulamanızdaki tüm blog yayınlarını döndürmüştür. Yeni bir blog yayını her eklendiğinde geri çağırma işlevi tüm yayınları döndürür.

Alt öğe eklendi

child_added etkinliği genellikle veritabanından öğe listesi alınırken kullanılır. Konumun tüm içeriğini döndüren value'ün aksine child_added, mevcut her alt öğe için bir kez ve daha sonra belirtilen yola her yeni alt öğe eklendiğinde tekrar tetiklenir. Etkinlik geri çağırma işlevine yeni çocuğun verilerini içeren bir anlık görüntü iletilir. Sıralama amacıyla, önceki alt öğenin anahtarını içeren ikinci bir bağımsız değişken de iletilir.

Blog uygulamanıza eklenen her yeni yayındaki yalnızca verileri almak istiyorsanız child_added işlevini kullanabilirsiniz:

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

Bu örnekte anlık görüntü, bağımsız bir blog yayını içeren bir nesne içerir. SDK, değeri alarak yayınları nesneye dönüştürdüğü için sırasıyla author ve title'ü çağırarak yayının yazarı ve başlık özelliklerine erişebilirsiniz. Ayrıca ikinci prevChildKey bağımsız değişkeninden önceki yayın kimliğine de erişebilirsiniz.

Alt öğe değiştirildi

child_changed etkinliği, bir alt öğe değiştirildiğinde tetiklenir. Buna, alt öğelerin torunlarında yapılan tüm değişiklikler de dahildir. Genellikle bir öğe listesindeki değişikliklere yanıt vermek için child_added ve child_removed ile birlikte kullanılır. Etkinlik geri çağırma işlevine iletilen anlık görüntü, alt öğeyle ilgili güncellenmiş verileri içerir.

Blog yayınları düzenlendiğinde güncellenen verileri okumak için child_changed'ü kullanabilirsiniz:

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

Çocuk Kaldırıldı

child_removed etkinliği, doğrudan alt öğe kaldırıldığında tetiklenir. Genellikle child_added ve child_changed ile birlikte kullanılır. Etkinlik geri çağırma işlevine iletilen anlık görüntü, kaldırılan alt öğenin verilerini içerir.

Blog örneğinde, silinen yayınla ilgili bir bildirimi konsola kaydetmek için child_removed öğesini kullanabilirsiniz:

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
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');
});

Çocuk Taşındı

child_moved etkinliği, sıralı verilerle çalışırken kullanılır. Bu konu sonraki bölümde ele alınmıştır.

Etkinlik Garantileri

Firebase veritabanı, etkinliklerle ilgili birkaç önemli garanti sunar:

Veritabanı Etkinliği Garantileri
Etkinlikler, yerel durum değiştiğinde her zaman tetiklenir.
Etkinlikler, yerel işlemlerin veya zamanlamanın geçici farklılıklara neden olduğu durumlarda bile (ör. ağ bağlantısının geçici olarak kaybedilmesi) verilerin doğru durumunu her zaman yansıtır.
Tek bir istemciden gelen yazma işlemleri her zaman sunucuya yazılır ve sırayla diğer kullanıcılara yayınlanır.
Değer etkinlikleri her zaman en son tetiklenir ve bu anlık görüntü alınmadan önce gerçekleşen diğer etkinliklerin güncellemelerini içereceği garanti edilir.

Değer etkinlikleri her zaman en son tetiklendiğinden aşağıdaki örnek her zaman işe yarayacaktır:

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

Geri çağırma işlevlerini kaldırma

Geri çağırma işlevleri, etkinlik türü ve kaldırılacak geri çağırma işlevi belirtilerek kaldırılır. Örneğin:

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

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

on() alanına bir kapsam bağlamı aktardıysanız geri aramayı ayırırken bu bağlam da aktarılmalıdır:

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

Bir konumdaki tüm geri aramaları kaldırmak istiyorsanız aşağıdakileri yapabilirsiniz:

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

Verileri Bir Kez Okuma

Bazı durumlarda, geri aramanın bir kez çağrılıp hemen kaldırılması yararlı olabilir. Bu işlemi kolaylaştırmak için bir yardımcı işlev oluşturduk:

Java
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
});
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)
}

Verileri sorgulama

Firebase veritabanı sorgularıyla, çeşitli faktörlere göre verileri seçerek alabilirsiniz. Veritabanında sorgu oluşturmak için sıralama işlevlerinden birini (orderByChild(), orderByKey() veya orderByValue()) kullanarak verilerinizin nasıl sıralanmasını istediğinizi belirtirsiniz. Ardından, karmaşık sorgular yürütmek için bunları diğer beş yöntemle birleştirebilirsiniz: limitToFirst(), limitToLast(), startAt(), endAt() ve equalTo().

Firebase'de hepimiz dinozorları çok havalı bulduğumuzdan, Firebase veritabanınızdaki verileri nasıl sorgulayabileceğinizi göstermek için dinozorlarla ilgili bilgiler içeren örnek bir veritabanından bir snippet kullanacağız:

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

Verileri üç şekilde sıralayabilirsiniz: alt anahtara, anahtara veya değere göre. Temel bir veritabanı sorgusu, aşağıdakilerden biri olan sıralama işlevlerinden biriyle başlar.

Belirtilen bir alt öğe anahtarına göre sıralama

Nodları ortak bir alt öğe anahtarına göre sıralamak için bu anahtarı orderByChild()'e iletebilirsiniz. Örneğin, tüm dinozorları boylarına göre sıralayarak okumak için aşağıdakileri yapabilirsiniz:

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
const ref = db.ref('dinosaurs');

ref.orderByChild('height').on('child_added', (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)
}

Sorguladığımız alt anahtarı içermeyen tüm düğümler null değeriyle sıralanır. Bu, sıralamada ilk sırada yer alacağı anlamına gelir. Verilerin nasıl sıralandığıyla ilgili ayrıntılı bilgi için Verilerin Sıralama Yöntemi bölümüne bakın.

Sorgular, yalnızca bir düzey aşağıda olan alt öğeler yerine derin iç içe yerleştirilmiş alt öğelere göre de sıralanabilir. Bu, aşağıdaki gibi derin iç içe yerleştirilmiş verileriniz varsa kullanışlıdır:

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

Artık yüksekliği sorgulamak için tek bir anahtar yerine nesnenin tam yolunu kullanabilirsiniz:

Java
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');
});
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)
}

Sorgular tek seferde yalnızca bir anahtara göre sıralanabilir. Aynı sorgu için orderByChild() işlevinin birden fazla kez çağrılması hata verir.

Anahtara göre sıralama

orderByKey() yöntemini kullanarak düğümleri anahtarlarına göre de sıralayabilirsiniz. Aşağıdaki örnekte, tüm dinozorlar alfabetik sırayla okunmaktadır:

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', (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)

Değere göre sıralama

orderByValue() yöntemini kullanarak düğümleri alt anahtarlarının değerine göre sıralayabilirsiniz. Dinozorların bir dino spor yarışması yaptığını ve puanlarını aşağıdaki biçimde takip ettiğinizi varsayalım:

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

Dinozorları puanlarına göre sıralamak için aşağıdaki sorguyu oluşturabilirsiniz:

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
const scoresRef = db.ref('scores');
scoresRef.orderByValue().on('value', (snapshot) => {
  snapshot.forEach((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)
}

orderByValue() kullanılırken null, boole, dize ve nesne değerlerinin nasıl sıralandığıyla ilgili açıklama için Verilerin Sıralama Şekli bölümüne bakın.

Karmaşık Sorgular

Verilerinizin nasıl sıralandığı artık net olduğundan daha karmaşık sorgular oluşturmak için aşağıda açıklanan limit veya range yöntemlerini kullanabilirsiniz.

Sınır Sorguları

limitToFirst() ve limitToLast() sorguları, belirli bir geri çağırma için senkronize edilecek maksimum alt öğe sayısını belirlemek amacıyla kullanılır. 100 sınırı belirlerseniz başlangıçta yalnızca 100 child_added etkinliği alırsınız. Veritabanında 100'den az mesaj varsa her mesaj için bir child_added etkinliği tetiklenir. Ancak 100'den fazla iletiniz varsa bu iletilerin yalnızca 100'ü için child_added etkinliği alırsınız. Bunlar, limitToFirst() kullanıyorsanız sıralanmış ilk 100 mesaj veya limitToLast() kullanıyorsanız sıralanmış son 100 mesajdır. Öğeler değiştikçe, sorguya giren öğeler için child_added etkinlik ve sorgudan çıkan öğeler için child_removed etkinlik alırsınız. Böylece toplam sayı 100'de kalır.

Dinozorlarla ilgili bilgiler veritabanını ve orderByChild()'ü kullanarak en ağır iki dinozoru bulabilirsiniz:

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

Veritabanında ikiden az dinozor depolanmadığı sürece child_added geri çağırma işlevi tam olarak iki kez tetiklenir. Ayrıca, veritabanına eklenen her yeni ve daha ağır dinozor için de tetiklenir. Python'da sorgu, doğrudan en ağır iki dinozoru içeren bir OrderedDict döndürür.

Benzer şekilde, limitToFirst() kullanarak en kısa iki dinozoru da bulabilirsiniz:

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

Veritabanında ikiden az dinozor depolanmadığı sürece child_added geri çağırma işlevi tam olarak iki kez tetiklenir. Ayrıca, ilk iki dinozordan biri veritabanından kaldırılırsa da tekrar tetiklenir. Bu durumda, ikinci en kısa dinozor yeni dinozor olur. Python'da sorgu, doğrudan en kısa dinozorları içeren bir OrderedDict döndürür.

orderByValue() ile sınır sorguları da yapabilirsiniz. En yüksek puana sahip ilk 3 dino spor dinozorunu içeren bir lider tablosu oluşturmak istiyorsanız aşağıdakileri yapabilirsiniz:

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
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());
  });
});
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)
}

Aralık Sorguları

startAt(), endAt() ve equalTo()'yi kullanmak, sorgularınız için rastgele başlangıç ve bitiş noktaları seçmenize olanak tanır. Örneğin, en az üç metre boyunda olan tüm dinozorları bulmak isterseniz orderByChild() ve startAt()'yi birleştirebilirsiniz:

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

Adları alfabetik olarak Pterodactyl'ten önce gelen tüm dinozorları bulmak için endAt() kullanabilirsiniz:

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

Sorgunuzun her iki ucunu da sınırlamak için startAt() ve endAt()'ü birleştirebilirsiniz. Aşağıdaki örnekte, adı "b" harfi ile başlayan tüm dinozorlar bulunur:

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', (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())
}

equalTo() yöntemi, tam eşlemelere göre filtreleme yapmanıza olanak tanır. Diğer aralık sorgularında olduğu gibi, eşleşen her alt düğüm için tetiklenir. Örneğin, 25 metre boyundaki tüm dinozorları bulmak için aşağıdaki sorguyu kullanabilirsiniz:

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

Aralık sorgular, verilerinizi sayfalara ayırmanız gerektiğinde de yararlıdır.

Tüm unsurların birleşimi

Karmaşık sorgular oluşturmak için bu tekniklerin tümünü birleştirebilirsiniz. Örneğin, Stegosaurus'tan biraz daha kısa olan dinozor adını bulabilirsiniz:

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
  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');
      }
    });
});
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")
}

Verilerin Sıralama Şekli

Bu bölümde, dört sıralama işlevinin her biri kullanıldığında verilerinizin nasıl sıralandığı açıklanmaktadır.

orderByChild

orderByChild() kullanıldığında, belirtilen alt anahtarı içeren veriler aşağıdaki gibi sıralanır:

  1. Belirtilen alt anahtar için null değerine sahip alt öğeler önce gelir.
  2. Ardından, belirtilen alt anahtar için false değerine sahip alt öğeler gelir. Birden fazla alt öğenin değeri false ise bu öğeler anahtara göre alfabetik olarak sıralanır.
  3. Ardından, belirtilen alt anahtar için true değerine sahip alt öğeler gelir. Birden fazla alt öğenin değeri true ise bu öğeler anahtara göre alfabetik olarak sıralanır.
  4. Ardından, sayısal değere sahip alt öğeler artan düzende sıralanır. Belirtilen alt öğe düğümü için aynı sayısal değere sahip birden fazla alt öğe varsa bunlar anahtara göre sıralanır.
  5. Dizelerin sırası, sayılardan sonra gelir ve alfabetik olarak artan düzendedir. Belirtilen alt öğe düğümü için birden fazla alt öğe aynı değere sahipse bu öğeler anahtara göre alfabetik olarak sıralanır.
  6. Nesneler en son gelir ve anahtara göre artan düzende alfabetik olarak sıralanır.

orderByKey

Verilerinizi sıralamak için orderByKey() kullanıldığında veriler, aşağıdaki gibi anahtara göre artan düzende döndürülür. Anahtarların yalnızca dize olabileceğini unutmayın.

  1. 32 bitlik tam sayı olarak ayrıştırılabilen bir anahtara sahip alt öğeler önce gelir ve artan düzende sıralanır.
  2. Anahtarı dize değeri olan alt öğeler, artan sözlük sırasına göre sıralanır.

orderByValue

orderByValue() kullanıldığında alt öğeler değerlerine göre sıralanır. Sıralama ölçütü, belirtilen alt anahtarın değeri yerine düğümün değeri kullanıldığı dışında orderByChild() ile aynıdır.