Abrufen von Daten

Dieses Dokument behandelt die Grundlagen des Abrufens von Datenbankdaten, die Reihenfolge der Daten und das Ausführen einfacher Datenabfragen. Der Datenabruf im Admin SDK wird in den verschiedenen Programmiersprachen leicht unterschiedlich implementiert.

  1. Asynchrone Zuhörer: Daten in einer Datenbank gespeichert Firebase Realtime abgerufen durch einen asynchronen Zuhörer auf eine Datenbank Bezug zu befestigen. Der Listener wird einmal für den Anfangszustand der Daten und jedes Mal, wenn sich die Daten ändern, getriggert. Ein Ereignis - Listener mehrere verschiedene empfangen Arten von Veranstaltungen . Dieser Datenabrufmodus wird in Java, Node.js und Python Admin SDKs unterstützt.
  2. Blocking lautet: Daten in einer Datenbank Firebase Realtime gespeichert wird durch den Aufruf einer blockierenden Verfahren auf einer Datenbankreferenz abgerufen, die die Daten an der Referenz gespeichert zurückgibt. Jeder Methodenaufruf ist ein einmaliger Vorgang. Das bedeutet, dass das SDK keine Rückrufe registriert, die auf nachfolgende Datenaktualisierungen lauschen. Dieses Modell des Datenabrufs wird in Python- und Go Admin-SDKs unterstützt.

Einstieg

Sehen wir uns das Blogging-Beispiel aus dem vorherigen Artikel noch einmal an, um zu verstehen, wie Daten aus einer Firebase-Datenbank gelesen werden. Daran erinnert , dass die Blog - Beiträge in dem Beispiel - App in der Datenbank gespeichert sind URL https://docs-examples.firebaseio.com/server/saving-data/fireblog/posts.json . Um Ihre Beitragsdaten zu lesen, können Sie Folgendes tun:

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 = admin.database();
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())
Gehen

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

Wenn Sie den obigen Code ausführen, sehen Sie ein Objekt, das alle Ihre Beiträge enthält, die in der Konsole protokolliert wurden. Im Fall von Node.js und Java wird die Listener-Funktion immer dann aufgerufen, wenn Ihrer Datenbankreferenz neue Daten hinzugefügt werden, und Sie müssen dafür keinen zusätzlichen Code schreiben.

In Java und Node.js empfängt die Callback - Funktion eine DataSnapshot , die eine Momentaufnahme der Daten ist. Ein Snapshot ist ein Bild der Daten einer bestimmten Datenbankreferenz zu einem einzigen Zeitpunkt. Aufruf val() / getValue() auf einem Schnappschuss kehrt die ein sprachspezifischen Objektdarstellung der Daten. Wenn keine Daten an der Position der Referenz existiert, wird der Snapshot des Wert null . Die get() Methode liefert eine in Python Python Darstellung der Daten direkt. Die Get() Funktion in Go entpackt die Daten in eine Datenstruktur gegeben.

Beachten Sie, dass wir den verwendeten value Ereignistyp in dem obigen Beispiel, die den gesamten Inhalt einer Firebase Datenbank Referenz liest, auch wenn nur ein Teil der Daten geändert. value ist eine der fünf verschiedenen Ereignistypen unten aufgeführt , die Sie verwenden können Daten aus der Datenbank zu lesen.

Ereignistypen in Java und Node.js lesen

Wert

Der value Ereignis wird verwendet , um eine statische Momentaufnahme der Inhalte zu einem bestimmten Datenbankpfad zu lesen, da sie zum Zeitpunkt des Leseereignisses vorlag. Es wird einmal mit den Anfangsdaten und bei jeder Datenänderung ausgelöst. Dem Ereignisrückruf wird ein Snapshot übergeben, der alle Daten an diesem Speicherort enthält, einschließlich untergeordneter Daten. Im Codebeispiel oben, value zurückgegeben alle Blog - Beiträge in der App. Jedes Mal, wenn ein neuer Blogbeitrag hinzugefügt wird, gibt die Rückruffunktion alle Beiträge zurück.

Kind hinzugefügt

Das child_added Ereignis wird normalerweise verwendet , wenn eine Liste von Elementen aus der Datenbank abgerufen werden . Im Gegensatz zu value , der den gesamten Inhalt der Lage zurückkehrt, child_added wird ausgelöst , wenn für jedes bestehendes Kind und dann wieder jedes Mal , wenn ein neues Kind auf den angegebenen Pfad hinzugefügt wird. Dem Ereignisrückruf wird ein Snapshot übergeben, der die Daten des neuen untergeordneten Elements enthält. Zu Ordnungszwecken wird ihm außerdem ein zweites Argument übergeben, das den Schlüssel des vorherigen untergeordneten Elements enthält.

Wenn Sie nur die Daten auf jedem neuen Beitrag hinzugefügt , um Ihre Blogging - App abrufen möchten, könnten Sie 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', (snapshot, prevChildKey) => {
  const newPost = snapshot.val();
  console.log('Author: ' + newPost.author);
  console.log('Title: ' + newPost.title);
  console.log('Previous Post ID: ' + prevChildKey);
});

In diesem Beispiel enthält der Snapshot ein Objekt mit einem individuellen Blogbeitrag. Da die SDK - Beiträge auf Objekte konvertiert , indem Sie den Wert abrufen, haben Sie Zugriff auf die Eigenschaften Autor und Titel Post durch den Aufruf author und title sind. Sie haben auch Zugang zu der früheren Post - ID aus dem zweiten prevChildKey Argumente.

Kind geändert

Das child_changed Ereignis wird ausgelöst , jedes Mal , wenn ein Kind Knoten geändert wird. Dies schließt alle Änderungen an Nachkommen des untergeordneten Knotens ein. Es wird in der Regel in Verbindung mit child_added und child_removed zu reagieren auf Änderungen an eine Liste von Elementen. Der an den Ereignisrückruf übergebene Snapshot enthält die aktualisierten Daten für das untergeordnete Element.

Sie können mit child_changed , um aktualisierte Daten auf Blog - Beiträge zu lesen , wenn sie bearbeitet werden:

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

Kind entfernt

Das child_removed Ereignis wird ausgelöst , wenn ein sofortiges Kind entfernt wird. Es wird in der Regel in Verbindung mit child_added und child_changed . Der an den Ereignisrückruf übergebene Snapshot enthält die Daten für das entfernte untergeordnete Element.

Im Blog können Sie beispielsweise verwenden child_removed eine Benachrichtigung über den gelöschten Beitrag an der Konsole anzumelden:

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

Kind umgezogen

Die child_moved Ereignis verwendet wird , wenn mit geordneten Daten arbeiten, die in der bedeckt ist nächsten Abschnitt .

Event-Garantien

Die Firebase-Datenbank bietet mehrere wichtige Garantien für Ereignisse:

Garantien für Datenbankereignisse
Ereignisse werden immer ausgelöst, wenn sich der lokale Zustand ändert.
Ereignisse spiegeln schließlich immer den korrekten Zustand der Daten wider, selbst in Fällen, in denen lokale Vorgänge oder Zeitabläufe vorübergehende Unterschiede verursachen, wie z. B. beim vorübergehenden Verlust der Netzwerkverbindung.
Schreibvorgänge von einem einzelnen Client werden immer auf den Server geschrieben und der Reihe nach an andere Benutzer gesendet.
Wertereignisse werden immer zuletzt ausgelöst und enthalten garantiert Updates von allen anderen Ereignissen, die vor der Erstellung dieses Snapshots aufgetreten sind.

Da Wertereignisse immer zuletzt ausgelöst werden, funktioniert das folgende Beispiel immer:

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

Rückrufe trennen

Rückrufe werden entfernt, indem der Ereignistyp und die zu entfernende Rückruffunktion wie folgt angegeben werden:

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

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

Wenn Sie einen Bereich Kontext in geben on() , muss sie übergeben werden , wenn der Rückruf Abnehmen:

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

Wenn Sie alle Rückrufe an einem Standort entfernen möchten, können Sie Folgendes tun:

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

Daten einmal lesen Data

In manchen Fällen kann es sinnvoll sein, einen Rückruf einmal anzurufen und dann sofort wieder zu entfernen. Wir haben eine Hilfsfunktion erstellt, um dies zu vereinfachen:

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

Daten abfragen

Mit Firebase-Datenbankabfragen können Sie Daten basierend auf verschiedenen Faktoren selektiv abrufen. Um eine Abfrage in der Datenbank aufzubauen, beginnen Sie mit der Angabe , wie Sie Ihre Daten bestellt werden unter Verwendung einer der Bestellfunktionen: orderByChild() , orderByKey() oder orderByValue() . Diese können Sie dann mit fünf anderen Methoden kombinieren komplexe Abfragen durchzuführen: limitToFirst() , limitToLast() , startAt() , endAt() und equalTo() .

Da wir alle bei Firebase der Meinung sind, dass Dinosaurier ziemlich cool sind, verwenden wir einen Ausschnitt aus einer Beispieldatenbank mit Dinosaurier-Fakten, um zu zeigen, wie Sie Daten in Ihrer Firebase-Datenbank abfragen können:

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

Sie können Daten auf drei Arten bestellen: mit einem Kind Schlüssel durch Schlüssel oder durch Wert. Eine grundlegende Datenbankabfrage beginnt mit einer dieser Sortierfunktionen, die im Folgenden erläutert werden.

Bestellung nach einem bestimmten untergeordneten Schlüssel

Sie können Knoten durch ein gemeinsames Kind Schlüssel bestellen , indem Sie den Schlüssel zum Passieren orderByChild() . Um beispielsweise alle Dinosaurier nach Größe sortiert zu lesen, können Sie Folgendes tun:

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))
Gehen

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

Jeder Knoten, der das Kind nicht Schlüssel verfügt wir die Abfrage auf mit einem Wert von sortierten null , dh es zuerst in der Reihenfolge kommen. Einzelheiten darüber , wie Daten bestellt wird, finden Sie im How Daten Abschnitt bestellt ist .

Abfragen können auch von tief verschachtelten Kindern geordnet werden, anstatt nur von Kindern eine Ebene darunter. Dies ist nützlich, wenn Sie über tief verschachtelte Daten wie diese verfügen:

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

Um jetzt die Höhe abzufragen, können Sie den vollständigen Pfad zum Objekt anstelle eines einzelnen Schlüssels verwenden:

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

Abfragen können jeweils nur nach einem Schlüssel sortiert werden. Der Aufruf orderByChild() mehrere Male auf der gleichen Abfrage wirft einen Fehler.

Bestellung per Schlüssel

Sie können auch Knoten , die durch ihre Schlüssel bestellen mit orderByKey() Methode. Das folgende Beispiel liest alle Dinosaurier in alphabetischer Reihenfolge:

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)
Gehen
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)

Bestellung nach Wert

Sie können Knoten durch den Wert ihres Kindes Schlüssel bestellen Sie die Verwendung von orderByValue() Methode. Nehmen wir an, die Dinosaurier haben einen Dino-Sportwettbewerb und Sie verfolgen ihre Ergebnisse im folgenden Format:

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

Um die Dinosaurier nach ihrer Punktzahl zu sortieren, könnten Sie die folgende Abfrage erstellen:

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

Siehe , wie Daten bestellt Abschnitt für eine Erklärung, wie null , boolean, String und Objektwerten sortiert werden bei der Verwendung von orderByValue() .

Komplexe Abfragen

Nun , da es klar ist , wie Sie Ihre Daten bestellt ist, können Sie den Grenzwert verwenden oder den Bereich unten beschriebenen Methoden komplexere Abfragen zu erstellen.

Abfragen begrenzen

Die limitToFirst() und limitToLast() Abfragen verwendet werden , eine maximale Anzahl von Kindern zu setzen für einen bestimmten Rückruf synchronisiert werden. Wenn Sie eine Grenze von 100 eingestellt, werden Sie zunächst erhalten nur auf 100 bis child_added Veranstaltungen. Wenn Sie weniger als 100 Meldungen in der Datenbank gespeichert sind, ein child_added wird Ereignis für jede Nachricht ausgelöst. Wenn Sie mehr als 100 Meldungen jedoch haben, werden Sie nur erhalten child_added Ereignis für 100 dieser Meldungen. Dies sind die ersten 100 bestellen Nachrichten , wenn Sie mit limitToFirst() oder die letzten 100 bestellen Nachrichten , wenn Sie mit limitToLast() . Als Elemente zu ändern, erhalten Sie child_added Ereignisse für Artikel , die die Abfrage und geben Sie child_removed Ereignisse für Gegenstände , die sie verlassen, so dass die Gesamtzahl bleibt bei 100.

Mit Hilfe der Dinosaurier Fakten Datenbank und orderByChild() , können Sie die beiden schwersten Dinosaurier finden:

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

Der child_added Rückruf wird genau zweimal ausgelöst, es sei denn , es gibt weniger als zwei in der Datenbank gespeichert sind Dinosaurier. Es wird auch für jeden neuen, schwereren Dinosaurier gefeuert, der der Datenbank hinzugefügt wird. In Python gibt die Abfrage direkt eine OrderedDict die beiden schwersten Dinosaurier enthält.

In ähnlicher Weise können Sie die beiden kürzesten Dinosaurier finden , indem Sie 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
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)
Gehen
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())
}

Der child_added Rückruf wird genau zweimal ausgelöst, es sei denn , es gibt weniger als zwei in der Datenbank gespeichert sind Dinosaurier. Es wird auch wieder gefeuert, wenn einer der ersten beiden Dinosaurier aus der Datenbank entfernt wird, da ein neuer Dinosaurier jetzt der zweitkürzeste ist. In Python gibt die Abfrage direkt eine OrderedDict die kürzesten Dinosaurier enthält.

Sie können auch Limit - Abfragen mit dirigieren orderByValue() . Wenn Sie eine Bestenliste mit den 3 Dino-Sportdinosauriern mit der höchsten Punktzahl erstellen möchten, können Sie Folgendes tun:

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

Bereichsabfragen

Mit startAt() , endAt() und equalTo() ermöglicht es Ihnen , beliebige Start- und Endpunkte für Ihre Fragen zur Verfügung. Zum Beispiel, wenn Sie alle Dinosaurier, die mindestens drei Meter hoch finden wollten, können Sie kombinieren orderByChild() und 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
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)
Gehen
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())
}

Sie können mit endAt() alle Dinosaurier , deren Namen kommen vor Pterodactyl finden lexikografisch:

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

Sie können kombinieren startAt() und endAt() beide Enden der Anfrage zu begrenzen. Das folgende Beispiel findet alle Dinosaurier, deren Name mit dem Buchstaben "b" beginnt:

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

Die equalTo() Methode ermöglicht es Ihnen, Filter basierend auf genauen Treffer. Wie bei den anderen Bereichsabfragen wird es für jeden übereinstimmenden untergeordneten Knoten ausgelöst. Mit der folgenden Abfrage können Sie beispielsweise alle Dinosaurier finden, die 25 Meter groß sind:

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

Bereichsabfragen sind auch nützlich, wenn Sie Ihre Daten paginieren müssen.

Alles zusammenfügen

Sie können all diese Techniken kombinieren, um komplexe Abfragen zu erstellen. Zum Beispiel können Sie den Namen des Dinosauriers finden, der nur kürzer als Stegosaurus ist:

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

Wie Daten bestellt werden

In diesem Abschnitt wird erläutert, wie Ihre Daten bei jeder der vier Bestellfunktionen bestellt werden.

orderByChild

Bei der Verwendung von orderByChild() , Daten , die der angegebene untergeordnete Schlüssel enthalten geordnet ist wie folgt:

  1. Kinder mit einem null - Wert für den angegebenen Schlüssel Kind an erster Stelle .
  2. Kinder mit einem Wert von false für den angegebenen Kind Schlüssel als nächstes kommen. Wenn mehrere Kinder einen Wert von false , werden sie sortiert lexikographisch durch Schlüssel.
  3. Kinder mit einem Wert von true für den angegebenen Kind Schlüssel als nächstes kommen. Wenn mehrere Kinder einen Wert von true , sie sind lexikographisch nach Schlüssel sortiert.
  4. Als nächstes folgen Kinder mit einem numerischen Wert, sortiert in aufsteigender Reihenfolge. Wenn mehrere untergeordnete Knoten denselben numerischen Wert für den angegebenen untergeordneten Knoten haben, werden sie nach dem Schlüssel sortiert.
  5. Strings kommen nach Zahlen und werden lexikographisch in aufsteigender Reihenfolge sortiert. Wenn mehrere Kinder denselben Wert für den angegebenen Kindknoten haben, werden sie lexikographisch nach Schlüssel sortiert.
  6. Die Objekte kommen zuletzt und sind lexikographisch nach Schlüssel in aufsteigender Reihenfolge sortiert.

orderByKey

Bei der Verwendung von orderByKey() Ihre Daten zu sortieren, werden die Daten zurückgegeben durch Schlüssel in aufsteigender Reihenfolge wie folgt. Beachten Sie, dass Schlüssel nur Zeichenfolgen sein können.

  1. Kinder mit einem Schlüssel, der als 32-Bit-Ganzzahl geparst werden kann, kommen zuerst, sortiert in aufsteigender Reihenfolge.
  2. Als nächstes kommen Kinder mit einem String-Wert als Schlüssel, lexikographisch aufsteigend sortiert.

orderByValue

Bei der Verwendung von orderByValue() werden die Kinder von ihrem Wert bestellt. Die Ordnungskriterien ist die gleiche wie in orderByChild() , außer der Wert des Knotens anstelle des Wertes eines bestimmten untergeordneten Schlüssel verwendet wird.