Veri Alma

Bu belgede, veritabanı verilerini alma, verilerin sıralanma şekli ve veriler üzerinde basit sorgular gerçekleştirme ile ilgili temel bilgiler verilmektedir. 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 bir dinleyici eklenerek alınır. Dinleyici, verilerin ilk durumu için bir kez, veriler her değiştiğinde ise tekrar tetiklenir. Bir etkinlik dinleyici, çeşitli farklı etkinlik türleri alabilir. Bu veri alma modu Java, Node.js ve Python Admin SDK'larında desteklenir.
  2. Okumaları engelleme: Firebase Realtime Database içinde depolanan veriler, bir veritabanı referansında 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şlemlerini kaydetmediği anlamına gelir. Bu veri alma modeli, Python ve Go Admin SDK'larında desteklenir.

Başlarken

Firebase veritabanındaki verileri nasıl okuyacağımızı anlamak için önceki makaledeki blog örneğine tekrar göz atalım. Ö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 tüm gönderilerinizin konsola kaydedildiği bir nesne görürsünüz. Node.js ve Java'da, veritabanı referansınıza yeni veriler eklendiğinde dinleyici işlevi çağrılır ve bu işlemin gerçekleşmesi için ek kod yazmanız gerekmez.

Java ve Node.js'de geri çağırma işlevi, verilerin anlık görüntüsü olan bir DataSnapshot alır. Anlık görüntü, belirli bir zamandaki belirli bir veritabanı referansındaki verilerin resmidir. Bir anlık görüntüde val() / getValue() çağrıldığında verilerin dile özgü nesne gösterimi 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 Python gösterimini doğrudan döndürür. Go'daki Get() işlevi, verileri belirli bir veri yapısına dönüştürür.

Yukarıdaki örnekte, yalnızca tek bir veri parçası değişse bile Firebase veritabanı referansının tüm içeriğini okuyan value etkinlik türünü kullandığımızı unutmayın. value, veritabanından veri 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, okuma etkinliği sırasında mevcut olduğu şekliyle, belirli bir veritabanı yolundaki içeriklerin statik bir anlık görüntüsünü okumak için kullanılır. İlk verilerle bir kez, veriler her değiştiğinde ise tekrar tetiklenir. Etkinlik geri çağırmasına, alt veriler de dahil olmak üzere o 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ürdü. Her yeni blog yayını eklendiğinde geri çağırma işlevi tüm yayınları döndürür.

Çocuk 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 işlevinin aksine, child_added işlevi her mevcut alt öğe için bir kez, belirtilen yola yeni bir alt öğe eklendiğinde ise tekrar tetiklenir. Etkinlik geri çağırmasına, yeni alt öğenin 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.

Yalnızca blog uygulamanıza eklenen her yeni yayındaki verileri almak istiyorsanız child_added 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üde tek bir blog yayını içeren bir nesne yer alır. SDK, değerini alarak gönderileri nesnelere dönüştürdüğünden sırasıyla author ve title çağrılarını yaparak gönderinin 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.

Çocuk Değiştirildi

Bir alt düğüm her değiştirildiğinde child_changed etkinliği tetiklenir. Çocuk düğümünün alt öğelerinde yapılan tüm değişiklikler buna 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ğırmasına iletilen anlık görüntü, çocuğa ait güncellenmiş verileri içerir.

Blog yayınları düzenlendiğinde güncellenen verileri okumak için child_changed simgesini 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 bir alt öğe kaldırıldığında tetiklenir. Genellikle child_added ve child_changed ile birlikte kullanılır. Etkinlik geri çağırmasına 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 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, sonraki bölümde ele alınan sıralı verilerle çalışırken kullanılır.

Etkinlik Garantileri

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

Veritabanı Etkinliği Garantileri
Etkinlikler, yerel durum değiştiğinde her zaman tetiklenir.
Yerel işlemlerin veya zamanlamanın geçici farklılıklara neden olduğu durumlarda (ör. ağ bağlantısının geçici olarak kaybolması) bile etkinlikler her zaman verilerin doğru durumunu yansıtır.
Tek bir istemciden gelen yazma işlemleri her zaman sunucuya yazılır ve diğer kullanıcılara sırayla 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 etkinliklerdeki güncellemeleri içerir.

Değer etkinlikleri her zaman en son tetiklendiğinden aşağıdaki örnek her zaman çalışı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ğırmaları Ayırma

Geri çağırmalar, 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() işlevine bir kapsam bağlamı ilettiyseniz geri çağırma ayrılırken de iletilmelidir:

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

Bir konumdaki tüm geri aramaları kaldırmak istiyorsanız şunları 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)
}

Veri Sorgulama

Firebase veritabanı sorgularıyla, çeşitli faktörlere göre verileri seçerek alabilirsiniz. Veritabanınızda bir sorgu oluşturmak için orderByChild(), orderByKey() veya orderByValue() sıralama işlevlerinden birini 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'deki herkes dinozorların çok havalı olduğunu düşündüğünden, Firebase veritabanınızdaki verilere nasıl sorgu uygulayabileceğinizi göstermek için dinozorlarla ilgili bilgilerin yer aldığı ö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ğıda açıklanan sıralama işlevlerinden biriyle başlar.

Belirli bir alt anahtara göre sıralama

orderByChild() işlevine bu anahtarı ileterek düğümleri ortak bir alt anahtara göre sıralayabilirsiniz. Örneğin, tüm dinozorları boylarına göre sıralanmış şekilde okumak için şunları 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(f'{key} was {val} meters tall')
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 anahtara sahip olmayan tüm düğümler null değeriyle sıralanır. Bu da sıralamada ilk sırada yer alacağı anlamına gelir. Verilerin nasıl sıralandığıyla ilgili ayrıntılı bilgi için Veriler Nasıl Sıralanır? bölümüne bakın.

Sorgular, yalnızca bir alt düzeydeki alt öğeler yerine derinlemesine 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
    }
  }
}

Yüksekliği sorgulamak için artık 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(f'{key} was {val} meters tall')
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 aynı anda yalnızca bir anahtara göre sıralanabilir. Aynı sorguda orderByChild() işlevini birden fazla kez çağırmak hataya neden olur.

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 okunur:

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 dino spor yarışması yaptığını ve skorları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(f'The {key} dinosaur\'s score is {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 Veriler Nasıl Sıralanır? bölümüne bakın.

Karmaşık Sorgular

Verilerinizin nasıl sıralandığı netleştiğine göre, daha karmaşık sorgular oluşturmak için aşağıda açıklanan limit veya range yöntemlerini kullanabilirsiniz.

Sorguları Sınırlama

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

Dinozorlarla ilgili bilgi 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şlemi 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üyor.

Benzer şekilde, limitToFirst() kullanarak en kısa iki dinozoru 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şlemi tam olarak iki kez tetiklenir. Ayrıca, ilk iki dinozordan biri veritabanından kaldırılırsa da tekrar tetiklenir. Çünkü artık yeni bir dinozor, en kısa ikinci dinozor olacaktır. Python'da sorgu, doğrudan en kısa dinozorları içeren bir OrderedDict döndürür.

Ayrıca orderByValue() ile sınır sorguları da yapabilirsiniz. En yüksek puanlı 3 dino spor dinozorunun yer aldığı bir skor 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(f'The {key} dinosaur\'s score is {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 kullanarak sorgularınız için rastgele başlangıç ve bitiş noktaları seçebilirsiniz. Örneğin, en az üç metre boyundaki tüm dinozorları bulmak istiyorsanız orderByChild() ve startAt() öğelerini 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ı sözlükbilimsel olarak Pterodactyl'den ö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() öğelerini birleştirebilirsiniz. Aşağıdaki örnekte, adı "b" harfiyle 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('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, her eşleşen alt düğüm için tetiklenir. Örneğin, 25 metre yüksekliğindeki 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 sayfalandı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 dinozorun 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(f'The dinosaur just shorter than the stegosaurus is {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")
}

Veriler Nasıl Sıralanır?

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

orderByChild

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

  1. Belirtilen çocuk anahtarı için null değeri olan çocuklar önce gelir.
  2. Belirtilen alt anahtar için false değerine sahip alt öğeler bir sonraki sırada yer alır. Birden fazla alt öğenin değeri false ise bunlar anahtara göre sözlük sırasına göre sıralanır.
  3. Belirtilen alt anahtar için true değerine sahip alt öğeler bir sonraki sırada yer alır. Birden fazla alt öğenin değeri true ise bunlar anahtara göre sözlük sırasına göre sıralanır.
  4. Sayısal değere sahip çocuklar, artan düzende sıralanarak gösterilir. Belirtilen alt düğüm için birden fazla alt öğe aynı sayısal değere sahipse bunlar anahtara göre sıralanır.
  5. Dizeler sayılardan sonra gelir ve sözlükbilimsel olarak artan düzende sıralanır. Belirtilen alt düğüm için birden fazla alt öğe aynı değere sahipse bunlar anahtara göre sözlük sırasına göre sıralanır.
  6. Nesneler en sona gelir ve anahtara göre sözlük sıralamasıyla artan düzende sıralanır.

orderByKey

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

  1. 32 bitlik bir tam sayı olarak ayrıştırılabilen anahtara sahip çocuklar, artan düzende sıralanarak ilk sırada yer alır.
  2. Anahtarı dize değeri olan çocuklar, sözlük sıralamasına göre artan düzende sıralanır.

orderByValue

orderByValue() kullanılırken çocuklar değerlerine göre sıralanır. Sıralama ölçütleri, orderByChild() ile aynıdır. Ancak belirtilen bir alt anahtarın değeri yerine düğümün değeri kullanılır.