Daten werden abgerufen

In diesem Dokument werden die Grundlagen des Abrufens von Daten sowie das Sortieren und Filtern von Firebase-Daten behandelt.

Hinweis

Bevor Sie Realtime Database verwenden können, müssen Sie Folgendes tun:

  • Registrieren Sie Ihr Unity-Projekt und konfigurieren Sie es für die Verwendung von Firebase.

    • Wenn Ihr Unity-Projekt bereits Firebase verwendet, ist es bereits für Firebase registriert und konfiguriert.

    • Wenn Sie kein Unity-Projekt haben, können Sie eine Beispiel-App herunterladen.

  • Fügen Sie das Firebase Unity SDK (insbesondere FirebaseDatabase.unitypackage) zu Ihrem Unity-Projekt hinzu.

Wenn Sie Firebase zu Ihrem Unity-Projekt hinzufügen, müssen Sie sowohl in der Firebase Console als auch in Ihrem offenen Unity-Projekt Aufgaben ausführen. Sie laden beispielsweise Firebase-Konfigurationsdateien aus der Console herunter und verschieben sie dann in Ihr Unity-Projekt.

Daten abrufen

Firebase-Daten werden entweder durch einen einmaligen Aufruf von GetValueAsync() oder durch Anhängen an ein Ereignis in einer FirebaseDatabase-Referenz abgerufen. Der Ereignis-Listener wird einmal für den Anfangszustand der Daten und dann jedes Mal aufgerufen, wenn sich die Daten ändern.

DatabaseReference abrufen

Zum Lesen von Daten aus der Datenbank benötigen Sie eine Instanz von DatabaseReference:

using Firebase;
using Firebase.Database;
using Firebase.Extensions.TaskExtension; // for ContinueWithOnMainThread

public class MyScript: MonoBehaviour {
  void Start() {
    // Get the root reference location of the database.
    DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference;
  }
}

Daten einmalig lesen

Mit der Methode GetValueAsync können Sie einen statischen Snapshot des Inhalts unter einem bestimmten Pfad einmalig lesen. Das Ergebnis der Aufgabe enthält einen Snapshot mit allen Daten an diesem Speicherort, einschließlich untergeordneter Daten. Wenn keine Daten vorhanden sind, ist der zurückgegebene Snapshot null.

    FirebaseDatabase.DefaultInstance
      .GetReference("Leaders")
      .GetValueAsync().ContinueWithOnMainThread(task =&gt {
        if (task.IsFaulted) {
          // Handle the error...
        }
        else if (task.IsCompleted) {
          DataSnapshot snapshot = task.Result;
          // Do something with snapshot...
        }
      });

Auf Ereignisse warten

Sie können Event-Listener hinzufügen, um über Änderungen an Daten informiert zu werden:

Ereignis Typische Verwendung
ValueChanged Änderungen am gesamten Inhalt eines Pfads lesen und darauf warten.
ChildAdded Listen mit Elementen abrufen oder auf Ergänzungen zu einer Liste mit Elementen warten. Empfohlene Verwendung mit ChildChanged und ChildRemoved, um Änderungen an Listen zu beobachten.
ChildChanged Änderungen an den Elementen in einer Liste beobachten. Verwenden Sie sie mit ChildAdded und ChildRemoved, um Änderungen an Listen zu beobachten.
ChildRemoved Auf das Entfernen von Elementen aus einer Liste warten. Verwenden Sie sie mit ChildAdded und ChildChanged, um Änderungen an Listen zu beobachten.
ChildMoved Änderungen an der Reihenfolge der Elemente in einer sortierten Liste überwachen. ChildMoved-Ereignisse folgen immer dem ChildChanged-Ereignis, das die Änderung der Reihenfolge des Elements verursacht hat (basierend auf Ihrer aktuellen order by-Methode).

ValueChanged-Ereignis

Mit dem Ereignis ValueChanged können Sie Änderungen am Inhalt eines bestimmten Pfads abonnieren. Dieses Ereignis wird einmal ausgelöst, wenn der Listener angehängt wird, und dann jedes Mal, wenn sich die Daten, einschließlich der untergeordneten Elemente, ändern. An den Ereignis-Callback wird ein Snapshot übergeben, der alle Daten an diesem Speicherort enthält, einschließlich untergeordneter Daten. Wenn keine Daten vorhanden sind, ist der zurückgegebene Snapshot null.

Das folgende Beispiel zeigt, wie ein Spiel die Punktzahlen einer Bestenliste aus der Datenbank abruft:

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders")
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

ValueChangedEventArgs enthält einen DataSnapshot mit den Daten am angegebenen Speicherort in der Datenbank zum Zeitpunkt des Ereignisses. Wenn Sie Value für einen Snapshot aufrufen, wird ein Dictionary<string, object> zurückgegeben, das die Daten darstellt. Wenn am Speicherort keine Daten vorhanden sind, wird beim Aufrufen von Value der Wert null zurückgegeben.

In diesem Beispiel wird auch args.DatabaseError geprüft, um festzustellen, ob der Lesevorgang abgebrochen wurde. Ein Lesevorgang kann beispielsweise abgebrochen werden, wenn der Client keine Berechtigung zum Lesen von einem Firebase-Datenbankspeicherort hat. In der DatabaseError wird angegeben, warum der Fehler aufgetreten ist.

Sie können das Ereignis später mit einem beliebigen DatabaseReference mit demselben Pfad abbestellen. DatabaseReference-Instanzen sind sitzungsspezifisch und können als Möglichkeit zum Zugriff auf beliebige Pfade und Abfragen betrachtet werden.

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders")
        .ValueChanged -= HandleValueChanged; // unsubscribe from ValueChanged.
    }

Untergeordnete Ereignisse

Untergeordnete Ereignisse werden als Reaktion auf bestimmte Vorgänge ausgelöst, die für die untergeordneten Elemente eines Knotens ausgeführt werden, z. B. wenn ein neues untergeordnetes Element über die Methode Push() hinzugefügt oder ein untergeordnetes Element über die Methode UpdateChildrenAsync() aktualisiert wird. Beide zusammen können nützlich sein, um auf Änderungen an einem bestimmten Knoten in einer Datenbank zu reagieren. In einem Spiel können diese Methoden beispielsweise zusammen verwendet werden, um die Aktivität in den Kommentaren einer Spielsitzung zu überwachen, wie unten gezeigt:

      var ref = FirebaseDatabase.DefaultInstance
      .GetReference("GameSessionComments");

      ref.ChildAdded += HandleChildAdded;
      ref.ChildChanged += HandleChildChanged;
      ref.ChildRemoved += HandleChildRemoved;
      ref.ChildMoved += HandleChildMoved;
    }

    void HandleChildAdded(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildChanged(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildRemoved(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

    void HandleChildMoved(object sender, ChildChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

Das Ereignis ChildAdded wird normalerweise verwendet, um eine Liste von Elementen in einer Firebase-Datenbank abzurufen. Das Ereignis ChildAdded wird einmal für jedes vorhandene untergeordnete Element und dann jedes Mal ausgelöst, wenn dem angegebenen Pfad ein neues untergeordnetes Element hinzugefügt wird. An den Listener wird ein Snapshot mit den Daten des neuen untergeordneten Elements übergeben.

Das Ereignis ChildChanged wird immer dann ausgelöst, wenn ein untergeordneter Knoten geändert wird. Dies schließt alle Änderungen an untergeordneten Knoten des untergeordneten Knotens ein. Sie wird normalerweise in Verbindung mit den Ereignissen ChildAdded und ChildRemoved verwendet, um auf Änderungen an einer Liste von Elementen zu reagieren. Der an den Event-Listener übergebene Snapshot enthält die aktualisierten Daten für das untergeordnete Element.

Das Ereignis ChildRemoved wird ausgelöst, wenn ein direktes untergeordnetes Element entfernt wird. Sie wird normalerweise in Verbindung mit den Callbacks ChildAdded und ChildChanged verwendet. Der an den Ereignis-Callback übergebene Snapshot enthält die Daten für das entfernte untergeordnete Element.

Das Ereignis ChildMoved wird immer dann ausgelöst, wenn das Ereignis ChildChanged durch eine Aktualisierung ausgelöst wird, die zu einer Neuanordnung des untergeordneten Elements führt. Sie wird mit Daten verwendet, die mit OrderByChild oder OrderByValue sortiert sind.

Daten sortieren und filtern

Mit der Realtime Database-Klasse Query können Sie Daten abrufen, die nach Schlüssel, Wert oder Wert eines untergeordneten Elements sortiert sind. Sie können das sortierte Ergebnis auch auf eine bestimmte Anzahl von Ergebnissen oder einen Bereich von Schlüsseln oder Werten filtern.

Daten sortieren

Wenn Sie sortierte Daten abrufen möchten, geben Sie zuerst eine der order by-Methoden an, um festzulegen, wie die Ergebnisse sortiert werden sollen:

Methode Nutzung
OrderByChild() Ordnet die Ergebnisse nach dem Wert eines angegebenen untergeordneten Schlüssels.
OrderByKey() Ergebnisse nach untergeordneten Schlüsseln sortieren.
OrderByValue() Ergebnisse nach untergeordneten Werten sortieren.

Sie können jeweils nur eine order by-Methode verwenden. Wenn eine order by-Methode mehrmals in derselben Abfrage aufgerufen wird, wird ein Fehler ausgegeben.

Im folgenden Beispiel wird gezeigt, wie Sie eine Bestenliste abonnieren können, die nach Punktzahl sortiert ist.

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders").OrderByChild("score")
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

Damit wird eine Abfrage definiert, die in Kombination mit einem valuechanged-Ereignis-Listener den Client mit der Bestenliste in der Datenbank synchronisiert, sortiert nach der Punktzahl der einzelnen Einträge. Weitere Informationen zur effizienten Strukturierung Ihrer Daten finden Sie unter Datenbank strukturieren.

Beim Aufruf der Methode OrderByChild() wird der untergeordnete Schlüssel angegeben, nach dem die Ergebnisse sortiert werden sollen. In diesem Fall werden die Ergebnisse nach dem Wert von "score" in jedem untergeordneten Element sortiert. Weitere Informationen zur Sortierung anderer Datentypen finden Sie unter Sortierung von Abfragedaten.

Daten filtern

Wenn Sie Daten filtern möchten, können Sie beim Erstellen einer Abfrage eine beliebige Limit- oder Bereichsmethode mit einer order by-Methode kombinieren.

Methode Nutzung
LimitToFirst() Legt die maximale Anzahl von Elementen fest, die ab dem Anfang der sortierten Ergebnisliste zurückgegeben werden sollen.
LimitToLast() Legt die maximale Anzahl der Elemente fest, die vom Ende der sortierten Ergebnisliste zurückgegeben werden sollen.
StartAt() Gibt Elemente zurück, die größer oder gleich dem angegebenen Schlüssel oder Wert sind, je nach gewählter order by-Methode.
EndAt() Gibt Elemente zurück, die kleiner oder gleich dem angegebenen Schlüssel oder Wert sind, je nach gewählter order by-Methode.
EqualTo() Gibt Elemente zurück, die dem angegebenen Schlüssel oder Wert entsprechen, je nach gewählter order by-Methode.

Im Gegensatz zu den order by-Methoden können Sie mehrere Limit- oder Bereichsfunktionen kombinieren. Sie können beispielsweise die Methoden StartAt() und EndAt() kombinieren, um die Ergebnisse auf einen bestimmten Wertebereich zu beschränken.

Auch wenn es nur eine einzige Übereinstimmung für die Abfrage gibt, ist der Snapshot immer noch eine Liste, die nur ein einzelnes Element enthält.

Anzahl der Ergebnisse begrenzen

Mit den Methoden LimitToFirst() und LimitToLast() können Sie die maximale Anzahl von untergeordneten Elementen festlegen, die für einen bestimmten Callback synchronisiert werden sollen. Wenn Sie beispielsweise mit LimitToFirst() ein Limit von 100 festlegen, erhalten Sie anfangs nur bis zu 100 ChildAdded-Callbacks. Wenn weniger als 100 Elemente in Ihrer Firebase-Datenbank gespeichert sind, wird für jedes Element ein ChildAdded-Callback ausgelöst.

Wenn sich Elemente ändern, erhalten Sie ChildAdded-Callbacks für Elemente, die in die Abfrage aufgenommen werden, und ChildRemoved-Callbacks für Elemente, die aus der Abfrage entfernt werden, sodass die Gesamtzahl bei 100 bleibt.

Der folgende Code gibt beispielsweise die Höchstpunktzahl aus einer Bestenliste zurück:

      FirebaseDatabase.DefaultInstance
        .GetReference("Leaders").OrderByChild("score").LimitToLast(1)
        .ValueChanged += HandleValueChanged;
    }

    void HandleValueChanged(object sender, ValueChangedEventArgs args) {
      if (args.DatabaseError != null) {
        Debug.LogError(args.DatabaseError.Message);
        return;
      }
      // Do something with the data in args.Snapshot
    }

Nach Schlüssel oder Wert filtern

Mit StartAt(), EndAt() und EqualTo() können Sie beliebige Start-, End- und Äquivalenzpunkte für Abfragen auswählen. Das kann nützlich sein, um Daten zu paginieren oder Elemente mit untergeordneten Elementen zu finden, die einen bestimmten Wert haben.

So werden Abfragedaten sortiert

In diesem Abschnitt wird erläutert, wie Daten nach den einzelnen order-by-Methoden in der Klasse Query sortiert werden.

OrderByChild

Wenn Sie OrderByChild() verwenden, werden Daten, die den angegebenen untergeordneten Schlüssel enthalten, so sortiert:

  1. Untergeordnete Elemente mit dem Wert null für den angegebenen untergeordneten Schlüssel stehen an erster Stelle.
  2. Als Nächstes folgen untergeordnete Elemente mit dem Wert false für den angegebenen untergeordneten Schlüssel. Wenn mehrere untergeordnete Elemente den Wert false haben, werden sie lexikografisch nach Schlüssel sortiert.
  3. Als Nächstes folgen untergeordnete Elemente mit dem Wert true für den angegebenen untergeordneten Schlüssel. Wenn mehrere untergeordnete Elemente den Wert true haben, werden sie lexikografisch nach Schlüssel sortiert.
  4. Als Nächstes folgen untergeordnete Elemente mit einem numerischen Wert, sortiert in aufsteigender Reihenfolge. Wenn mehrere untergeordnete Elemente denselben numerischen Wert für den angegebenen untergeordneten Knoten haben, werden sie nach Schlüssel sortiert.
  5. Strings werden nach Zahlen aufgeführt und lexikografisch in aufsteigender Reihenfolge sortiert. Wenn mehrere untergeordnete Elemente denselben Wert für den angegebenen untergeordneten Knoten haben, werden sie lexikografisch nach Schlüssel sortiert.
  6. Objekte kommen zuletzt und werden lexikografisch nach Schlüssel in aufsteigender Reihenfolge sortiert.

OrderByKey

Wenn Sie OrderByKey() zum Sortieren Ihrer Daten verwenden, werden die Daten in aufsteigender Reihenfolge nach Schlüssel zurückgegeben.

  1. Untergeordnete Elemente mit einem Schlüssel, der als 32-Bit-Ganzzahl geparst werden kann, werden zuerst angezeigt, sortiert in aufsteigender Reihenfolge.
  2. Als Nächstes folgen untergeordnete Elemente mit einem Stringwert als Schlüssel, die lexikografisch in aufsteigender Reihenfolge sortiert sind.

OrderByValue

Wenn Sie OrderByValue() verwenden, werden die untergeordneten Elemente nach ihrem Wert sortiert. Die Sortierkriterien sind dieselben wie in OrderByChild(), mit der Ausnahme, dass der Wert des Knotens anstelle des Werts eines angegebenen untergeordneten Schlüssels verwendet wird.