Daten speichern

Möglichkeiten zum Speichern von Daten

PUT Daten in einen definierten Pfad schreiben oder ersetzen, z. B. fireblog/users/user1/<data>
PATCH Einige Schlüssel für einen definierten Pfad aktualisieren, ohne alle Daten zu ersetzen.
POST Einer Datenliste in unserer Firebase-Datenbank hinzufügen Jedes Mal, wenn wir eine POST-Anfrage senden, generiert der Firebase-Client einen eindeutigen Schlüssel, z. B. fireblog/users/<unique-id>/<data>.
LÖSCHEN Daten aus der angegebenen Firebase-Datenbankreferenz entfernen.

Daten mit PUT schreiben

Der grundlegende Schreibvorgang über die REST API ist PUT. Um das Speichern von Daten zu veranschaulichen, erstellen wir eine Blogging-Anwendung mit Beiträgen und Nutzern. Alle Daten für unsere Anwendung werden unter dem Pfad „fireblog“ unter der Firebase-Datenbank-URL „https://docs-examples.firebaseio.com/fireblog“ gespeichert.

Speichern wir zuerst einige Nutzerdaten in unserer Firebase-Datenbank. Wir speichern jeden Nutzer mit einem eindeutigen Nutzernamen sowie seinem vollständigen Namen und seinem Geburtsdatum. Da jeder Nutzer einen eindeutigen Nutzernamen hat, ist es sinnvoll, hier PUT anstelle von POST zu verwenden, da wir den Schlüssel bereits haben und keinen erstellen müssen.

Mit PUT können wir einen String, eine Zahl, einen booleschen Wert, ein Array oder ein beliebiges JSON-Objekt in unsere Firebase-Datenbank schreiben. In diesem Fall übergeben wir ihm ein Objekt:

curl -X PUT -d '{
  "alanisawesome": {
    "name": "Alan Turing",
    "birthday": "June 23, 1912"
  }
}' 'https://docs-examples.firebaseio.com/fireblog/users.json'

Wenn ein JSON-Objekt in der Datenbank gespeichert wird, werden die Objekteigenschaften automatisch verschachtelt den untergeordneten Speicherorten zugeordnet. Wenn Sie den neu erstellten Knoten aufrufen, sehen Sie den Wert „Alan Turing“. Wir können Daten auch direkt an einem untergeordneten Speicherort speichern:

curl -X PUT -d '"Alan Turing"' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/name.json'
curl -X PUT -d '"June 23, 1912"' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome/birthday.json'

In den beiden obigen Beispielen wird der Wert gleichzeitig mit einem Objekt und separat in untergeordnete Speicherorte geschrieben. In beiden Fällen werden dieselben Daten in unserer Firebase-Datenbank gespeichert:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing"
    }
  }
}

Eine erfolgreiche Anfrage wird durch einen HTTP-Statuscode 200 OK angezeigt. Die Antwort enthält die Daten, die wir in die Datenbank geschrieben haben. Im ersten Beispiel wird nur ein Ereignis auf Clients ausgelöst, die die Daten beobachten, während im zweiten Beispiel zwei Ereignisse ausgelöst werden. Wenn am Nutzerpfad bereits Daten vorhanden sind, werden diese beim ersten Ansatz überschrieben. Bei der zweiten Methode wird dagegen nur der Wert jedes einzelnen untergeordneten Knotens geändert, während andere untergeordnete Knoten unverändert bleiben. PUT entspricht set() in unserem JavaScript SDK.

Daten mit PATCH aktualisieren

Mit einer PATCH-Anfrage können wir bestimmte Kinder an einem Standort aktualisieren, ohne vorhandene Daten zu überschreiben. Fügen wir den Nutzerdaten von Turing mit einer PATCH-Anfrage seinen Spitznamen hinzu:

curl -X PATCH -d '{
  "nickname": "Alan The Machine"
}' \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'

Durch die obige Anfrage wird nickname in das alanisawesome-Objekt geschrieben, ohne dass die untergeordneten Elemente name oder birthday gelöscht werden. Wenn wir hier stattdessen eine PUT-Anfrage gestellt hätten, wären name und birthday gelöscht worden, da sie nicht in der Anfrage enthalten waren. Die Daten in unserer Firebase-Datenbank sehen jetzt so aus:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing",
      "nickname": "Alan The Machine"
    }
  }
}

Eine erfolgreiche Anfrage wird durch einen HTTP-Statuscode 200 OK angezeigt. Die Antwort enthält die aktualisierten Daten, die in die Datenbank geschrieben wurden.

Firebase unterstützt auch Aktualisierungen für mehrere Pfade. Das bedeutet, dass PATCH jetzt Werte an mehreren Stellen in Ihrer Firebase-Datenbank gleichzeitig aktualisieren kann. Das ist eine leistungsstarke Funktion, mit der Sie Ihre Daten denormalisieren können. Mithilfe von Multipath-Updates können wir Alan und Grace gleichzeitig Spitznamen hinzufügen:

curl -X PATCH -d '{
  "alanisawesome/nickname": "Alan The Machine",
  "gracehopper/nickname": "Amazing Grace"
}' \
  'https://docs-examples.firebaseio.com/fireblog/users.json'

Nach dieser Aktualisierung wurden sowohl Alan als auch Grace ihre Spitznamen hinzugefügt:

{
  "users": {
    "alanisawesome": {
      "date_of_birth": "June 23, 1912",
      "full_name": "Alan Turing",
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "date_of_birth": "December 9, 1906",
      "full_name": "Grace Hopper",
      "nickname": "Amazing Grace"
    }
  }
}

Wenn Sie versuchen, Objekte durch Schreiben von Objekten mit den enthaltenen Pfaden zu aktualisieren, führt dies zu einem anderen Verhalten. Sehen wir uns an, was passiert, wenn wir versuchen, Grace und Alan so zu aktualisieren:

curl -X PATCH -d '{
  "alanisawesome": {"nickname": "Alan The Machine"},
  "gracehopper": {"nickname": "Amazing Grace"}
}' \
  'https://docs-examples.firebaseio.com/fireblog/users.json'

Das führt zu einem anderen Verhalten, nämlich zum Überschreiben des gesamten /fireblog/users-Knotens:

{
  "users": {
    "alanisawesome": {
      "nickname": "Alan The Machine"
    },
    "gracehop": {
      "nickname": "Amazing Grace"
    }
  }
}

Daten mit bedingten Anfragen aktualisieren

Sie können bedingte Anfragen verwenden, das REST-Äquivalent zu Transaktionen, um Daten gemäß ihrem vorhandenen Status zu aktualisieren. Wenn du beispielsweise einen Zähler für „Mag ich“ erhöhen möchtest und dafür sorgen möchtest, dass die Anzahl mehrerer gleichzeitiger „Mag ich“-Bewertungen korrekt erfasst wird, kannst du eine bedingte Anfrage verwenden, um den neuen Wert in den Zähler zu schreiben. Anstatt zwei Schreibvorgänge, die den Zähler auf dieselbe Zahl ändern, schlägt eine der Schreibanfragen fehl und Sie können die Anfrage dann mit dem neuen Wert wiederholen.
  1. Wenn Sie eine bedingte Anfrage an einem Standort ausführen möchten, rufen Sie die eindeutige Kennung für die aktuellen Daten an diesem Standort oder das ETag ab. Wenn sich die Daten an diesem Speicherort ändern, ändert sich auch das ETag. Sie können ein ETag mit einer anderen Methode als PATCH anfordern. Im folgenden Beispiel wird eine GET-Anfrage verwendet.
    curl -i 'https://test.example.com/posts/12345/upvotes.json' -H 'X-Firebase-ETag: true'
    Wenn du das ETag im Header aufrufst, wird das ETag des angegebenen Speicherorts in der HTTP-Antwort zurückgegeben.
    HTTP/1.1 200 OK
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    ETag: [ETAG_VALUE]
    Cache-Control: no-cache
    
    10 // Current value of the data at the specified location
  2. Fügen Sie den zurückgegebenen ETag in Ihre nächste PUT- oder DELETE-Anfrage ein, um Daten zu aktualisieren, die genau mit diesem ETag-Wert übereinstimmen. Wenn Sie in unserem Beispiel den Zähler auf „11“ aktualisieren möchten, also um 1 größer als der ursprünglich abgerufene Wert „10“, und die Anfrage fehlschlagen lassen möchten, wenn der Wert nicht mehr übereinstimmt, verwenden Sie den folgenden Code:
    curl -iX PUT -d '11' 'https://[PROJECT_ID].firebaseio.com/posts/12345/upvotes.json' -H 'if-match:[ETAG_VALUE]'
    Wenn der Wert der Daten am angegebenen Speicherort immer noch 10 beträgt, stimmt das ETag in der PUT-Anfrage überein und die Anfrage ist erfolgreich. Dabei wird 11 in die Datenbank geschrieben.
    HTTP/1.1 200 OK
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    Cache-Control: no-cache
    
    11 // New value of the data at the specified location, written by the conditional request
    Wenn der Speicherort nicht mehr mit dem ETag übereinstimmt, was z. B. passieren kann, wenn ein anderer Nutzer einen neuen Wert in die Datenbank geschrieben hat, schlägt die Anfrage fehl, ohne dass etwas an den Speicherort geschrieben wird. Die Rückgabeantwort enthält den neuen Wert und das ETag.
    HTTP/1.1 412 Precondition Failed
    Content-Length: 6
    Content-Type: application/json; charset=utf-8
    Access-Control-Allow-Origin: *
    ETag: [ETAG_VALUE]
    Cache-Control: no-cache
    
    12 // New value of the data at the specified location
  3. Verwenden Sie die neuen Informationen, wenn Sie die Anfrage noch einmal senden möchten. Realtime Database wiederholt bedingte Anfragen, die fehlgeschlagen sind, nicht automatisch. Sie können jedoch den neuen Wert und das ETag verwenden, um eine neue bedingte Anfrage mit den Informationen zu erstellen, die in der Fehlerantwort zurückgegeben wurden.

Bei REST-basierten bedingten Anfragen wird der HTTP-Standard if-match implementiert. Sie unterscheiden sich jedoch in den folgenden Punkten vom Standard:

  • Für jede if-Match-Anfrage kann nur ein ETag-Wert angegeben werden, nicht mehrere.
  • Während der Standard vorschlägt, dass ETags mit allen Anfragen zurückgegeben werden, gibt Realtime Database nur ETags mit Anfragen zurück, die den Header X-Firebase-ETag enthalten. Dies reduziert die Abrechnungskosten für Standardanfragen.

Bedingte Anfragen sind außerdem möglicherweise langsamer als normale REST-Anfragen.

Datenlisten speichern

Um für jedes untergeordnete Element, das einer Firebase-Datenbankreferenz hinzugefügt wird, einen eindeutigen, zeitstempelbasierten Schlüssel zu generieren, können wir eine POST-Anfrage senden. Für unseren users-Pfad war es sinnvoll, eigene Schlüssel zu definieren, da jeder Nutzer einen eindeutigen Nutzernamen hat. Wenn Nutzer der App jedoch Blogposts hinzufügen, verwenden wir eine POST-Anfrage, um automatisch einen Schlüssel für jeden Blogpost zu generieren:

curl -X POST -d '{
  "author": "alanisawesome",
  "title": "The Turing Machine"
}' 'https://docs-examples.firebaseio.com/fireblog/posts.json'

Unser posts-Pfad enthält jetzt die folgenden Daten:

{
  "posts": {
    "-JSOpn9ZC54A4P4RoqVa": {
      "author": "alanisawesome",
      "title": "The Turing Machine"
    }
  }
}

Der Schlüssel -JSOpn9ZC54A4P4RoqVa wurde automatisch für uns generiert, da wir eine POST-Anfrage verwendet haben. Eine erfolgreiche Anfrage wird durch einen 200 OK-HTTP-Statuscode angezeigt. Die Antwort enthält den Schlüssel der hinzugefügten neuen Daten:

{"name":"-JSOpn9ZC54A4P4RoqVa"}

Daten entfernen

Um Daten aus der Datenbank zu entfernen, können wir eine DELETE-Anfrage mit der URL des Pfads senden, aus dem wir Daten löschen möchten. Mit dem folgenden Befehl wird Alan aus dem Pfad users gelöscht:

curl -X DELETE \
  'https://docs-examples.firebaseio.com/fireblog/users/alanisawesome.json'

Eine erfolgreiche DELETE-Anfrage wird durch einen 200 OK-HTTP-Statuscode mit einer Antwort im JSON-Format null angezeigt.

URI-Parameter

Die REST API akzeptiert die folgenden URI-Parameter beim Schreiben von Daten in die Datenbank:

auth

Der Anfrageparameter auth ermöglicht den Zugriff auf Daten, die durch Firebase Realtime Database Security Rules geschützt sind, und wird von allen Anfragetypen unterstützt. Das Argument kann entweder unser Firebase-App-Secret oder ein Authentifizierungstoken sein, das im Abschnitt zur Nutzerautorisierung erläutert wird. Im folgenden Beispiel wird eine POST-Anfrage mit einem auth-Parameter gesendet, wobei CREDENTIAL entweder das Firebase-App-Secret oder ein Authentifizierungstoken ist:

curl -X POST -d '{"Authenticated POST request"}' \
  'https://docs-examples.firebaseio.com/auth-example.json?auth=CREDENTIAL'

ausgeben

Mit dem Parameter print können wir das Format der Antwort aus der Datenbank angeben. Wenn wir print=pretty zur Anfrage hinzufügen, werden die Daten in einem für Menschen lesbaren Format zurückgegeben. print=pretty wird von GET-, PUT-, POST-, PATCH- und DELETE-Anfragen unterstützt.

Wenn wir die Ausgabe vom Server beim Schreiben von Daten unterdrücken möchten, können wir unserer Anfrage print=silent hinzufügen. Die resultierende Antwort ist leer und wird durch einen HTTP-Statuscode von 204 No Content angezeigt, wenn die Anfrage erfolgreich war. Die print=silent wird von GET-, PUT-, POST- und PATCH-Anfragen unterstützt.

Serverwerte schreiben

Serverwerte können an einem Speicherort mit einem Platzhalterwert geschrieben werden. Das ist ein Objekt mit einem einzelnen ".sv"-Schlüssel. Der Wert für diesen Schlüssel ist der Serverwert, den wir festlegen möchten. Um beispielsweise einen Zeitstempel für das Erstellen eines Nutzers festzulegen, könnten Sie Folgendes tun:

curl -X PUT -d '{".sv": "timestamp"}' \
  'https://docs-examples.firebaseio.com/alanisawesome/createdAt.json'

"timestamp" ist der einzige unterstützte Serverwert und gibt die Zeit seit der UNIX-Epoche in Millisekunden an.

Schreibleistung verbessern

Wenn wir große Datenmengen in die Datenbank schreiben, können wir mit dem Parameter print=silent die Schreibleistung verbessern und die Bandbreitennutzung verringern. Beim normalen Schreibverhalten antwortet der Server mit den geschriebenen JSON-Daten. Wenn print=silent angegeben ist, trennt der Server die Verbindung nach dem Empfang der Daten sofort, wodurch die Bandbreitennutzung reduziert wird.

Wenn wir viele Anfragen an die Datenbank senden, können wir die HTTPS-Verbindung wiederverwenden, indem wir eine Keep-Alive-Anfrage im HTTP-Header senden.

Fehlerbedingungen

In den folgenden Fällen gibt die REST API Fehlercodes zurück:

HTTP-Statuscodes
400 Ungültige Anfrage

Eine der folgenden Fehlerbedingungen:

  • PUT- oder POST-Daten konnten nicht geparst werden.
  • Fehlende PUT- oder POST-Daten
  • Bei der Anfrage wird versucht, zu große PUT- oder POST-Daten zu PUT.
  • Der REST API-Aufruf enthält ungültige untergeordnete Namen als Teil des Pfads.
  • Der REST API-Aufrufpfad ist zu lang.
  • Die Anfrage enthält einen unbekannten Serverwert.
  • Der Index für die Abfrage ist nicht in Ihrer Firebase Realtime Database Security Rules definiert.
  • Die Anfrage unterstützt keinen der angegebenen Abfrageparameter.
  • Die Anfrage enthält Abfrageparameter und eine flache GET-Anfrage.
401 Nicht autorisiert

Eine der folgenden Fehlerbedingungen:

  • Das Authentifizierungstoken ist abgelaufen.
  • Das in der Anfrage verwendete Authentifizierungstoken ist ungültig.
  • Die Authentifizierung mit einem access_token ist fehlgeschlagen.
  • Die Anfrage verstößt gegen Ihre Firebase Realtime Database Security Rules.
404 Nicht gefunden Die angegebene Firebase-Datenbank wurde nicht gefunden.
500 Interner Serverfehler Der Server hat einen Fehler zurückgegeben. Weitere Informationen finden Sie in der Fehlermeldung.
503 – Dienst nicht verfügbar Die angegebene Firebase Realtime Database ist vorübergehend nicht verfügbar. Die Anfrage wurde daher nicht ausgeführt.

Daten schützen

Firebase bietet eine Sicherheitssprache, mit der wir festlegen können, welche Nutzer Lese- und Schreibzugriff auf verschiedene Knoten unserer Daten haben. Weitere Informationen dazu finden Sie unter Realtime Database Security Rules.

Nachdem wir über das Speichern von Daten gesprochen haben, können wir im nächsten Abschnitt lernen, wie wir Daten über die REST API aus der Firebase-Datenbank abrufen.