La sauvegarde des données

Façons de sauvegarder des données

METTRE Écrivez ou remplacez des données dans un chemin défini , comme fireblog/users/user1/<data>
CORRECTIF Mettez à jour certaines clés d'un chemin défini sans remplacer toutes les données.
POSTE Ajoutez à une liste de données dans notre base de données Firebase. Chaque fois que nous envoyons une requête POST , le client Firebase génère une clé unique, comme fireblog/users/<unique-id>/<data>
SUPPRIMER Supprimez les données de la référence de base de données Firebase spécifiée.

Écrire des données avec PUT

L'opération d'écriture de base via l'API REST est PUT . Pour démontrer la sauvegarde des données, nous allons créer une application de blog avec des articles et des utilisateurs. Toutes les données de notre application seront stockées sous le chemin « fireblog », à l'URL de la base de données Firebase « https://docs-examples.firebaseio.com/fireblog ».

Commençons par enregistrer certaines données utilisateur dans notre base de données Firebase. Nous stockerons chaque utilisateur sous un nom d'utilisateur unique, ainsi que son nom complet et sa date de naissance. Puisque chaque utilisateur aura un nom d'utilisateur unique, il est logique d'utiliser PUT ici au lieu de POST puisque nous avons déjà la clé et n'avons pas besoin d'en créer une.

En utilisant PUT , nous pouvons écrire une chaîne, un nombre, un booléen, un tableau ou tout autre objet JSON dans notre base de données Firebase. Dans ce cas nous lui passerons un objet :

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

Lorsqu'un objet JSON est enregistré dans la base de données, les propriétés de l'objet sont automatiquement mappées aux emplacements enfants de manière imbriquée. Si nous naviguons vers le nœud nouvellement créé, nous verrons la valeur « Alan Turing ». Nous pouvons également enregistrer les données directement dans un emplacement enfant :

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'

Les deux exemples ci-dessus (écrire la valeur en même temps qu'un objet et les écrire séparément dans les emplacements enfants) entraîneront l'enregistrement des mêmes données dans notre base de données Firebase :

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

Une demande réussie sera indiquée par un code d'état HTTP 200 OK et la réponse contiendra les données que nous avons écrites dans la base de données. Le premier exemple ne déclenchera qu'un seul événement sur les clients qui surveillent les données, tandis que le deuxième exemple en déclenchera deux. Il est important de noter que si des données existaient déjà sur le chemin de l'utilisateur, la première approche les écraserait, mais la seconde méthode ne modifierait que la valeur de chaque nœud enfant distinct tout en laissant les autres enfants inchangés. PUT équivaut à set() dans notre SDK JavaScript.

Mise à jour des données avec PATCH

À l'aide d'une requête PATCH , nous pouvons mettre à jour des enfants spécifiques à un emplacement sans écraser les données existantes. Ajoutons le pseudo de Turing à ses données utilisateur avec une requête PATCH :

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

La requête ci-dessus écrira nickname à notre objet alanisawesome sans supprimer le name ou les enfants birthday . Notez que si nous avions émis une requête PUT ici à la place, name et birthday auraient été supprimés car ils n'étaient pas inclus dans la requête. Les données de notre base de données Firebase ressemblent désormais à ceci :

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

Une demande réussie sera indiquée par un code d'état HTTP 200 OK et la réponse contiendra les données mises à jour écrites dans la base de données.

Firebase prend également en charge les mises à jour multi-chemins. Cela signifie que PATCH peut désormais mettre à jour les valeurs à plusieurs emplacements de votre base de données Firebase en même temps, une fonctionnalité puissante qui vous aide à dénormaliser vos données . Grâce aux mises à jour multi-chemins, nous pouvons ajouter des surnoms à Alan et Grace en même temps :

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

Après cette mise à jour, Alan et Grace ont vu leurs surnoms ajoutés :

{
  "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"
    }
  }
}

Notez qu'essayer de mettre à jour des objets en écrivant des objets avec les chemins inclus entraînera un comportement différent. Jetons un coup d'œil à ce qui se passe si nous essayons plutôt de mettre à jour Grace et Alan de cette façon :

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

Cela entraîne un comportement différent, à savoir l'écrasement de l'intégralité du nœud /fireblog/users :

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

Mise à jour des données avec des demandes conditionnelles

Vous pouvez utiliser des requêtes conditionnelles, l'équivalent REST des transactions, pour mettre à jour les données en fonction de leur état existant. Par exemple, si vous souhaitez augmenter un compteur de votes positifs et vous assurer que le décompte reflète avec précision plusieurs votes positifs simultanés, utilisez une requête conditionnelle pour écrire la nouvelle valeur dans le compteur. Au lieu de deux écritures qui modifient le compteur avec le même nombre, l'une des demandes d'écriture échoue et vous pouvez ensuite réessayer la demande avec la nouvelle valeur.
  1. Pour effectuer une requête conditionnelle à un emplacement, obtenez l'identifiant unique des données actuelles à cet emplacement, ou l'ETag. Si les données changent à cet emplacement, l'ETag change également. Vous pouvez demander un ETag avec n’importe quelle méthode autre que PATCH . L'exemple suivant utilise une requête GET .
    curl -i 'https://test.example.com/posts/12345/upvotes.json' -H 'X-Firebase-ETag: true'
    
    L'appel spécifique de l'ETag dans l'en-tête renvoie l'ETag de l'emplacement spécifié dans la réponse HTTP.
    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. Incluez l'ETag renvoyé dans votre prochaine requête PUT ou DELETE pour mettre à jour les données qui correspondent spécifiquement à cette valeur ETag. En suivant notre exemple, pour mettre à jour le compteur à 11, ou 1 supérieur à la valeur initiale récupérée de 10, et faire échouer la requête si la valeur ne correspond plus, utilisez le code suivant :
    curl -iX PUT -d '11' 'https://[PROJECT_ID].firebaseio.com/posts/12345/upvotes.json' -H 'if-match:[ETAG_VALUE]'
    
    Si la valeur des données à la valeur spécifiée l'emplacement est toujours 10, l'ETag dans la requête PUT correspond et la requête réussit, écrivant 11 dans la base de données.
    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
    
    Si l'emplacement ne correspond plus à l'ETag, ce qui pourrait se produire si un autre utilisateur écrivait une nouvelle valeur dans la base de données, la requête échoue sans écrire à l'emplacement. La réponse de retour inclut la nouvelle valeur et 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. Utilisez les nouvelles informations si vous décidez de réessayer la demande. Realtime Database ne réessaye pas automatiquement les requêtes conditionnelles qui ont échoué. Cependant, vous pouvez utiliser la nouvelle valeur et ETag pour créer une nouvelle demande conditionnelle avec les informations renvoyées par la réponse d'échec.

Les requêtes conditionnelles basées sur REST implémentent la norme HTTP if-match . Cependant, ils diffèrent de la norme sur les points suivants :

  • Vous ne pouvez fournir qu'une seule valeur ETag pour chaque demande if-match, et non plusieurs.
  • Alors que la norme suggère que les ETags soient renvoyés avec toutes les requêtes, Realtime Database renvoie uniquement les ETags avec les requêtes incluant l'en-tête X-Firebase-ETag . Cela réduit les coûts de facturation pour les demandes standards.

Les requêtes conditionnelles peuvent également être plus lentes que les requêtes REST classiques.

Enregistrement de listes de données

Pour générer une clé unique basée sur un horodatage pour chaque enfant ajouté à une référence de base de données Firebase, nous pouvons envoyer une requête POST . Pour notre parcours users , il était logique de définir nos propres clés puisque chaque utilisateur possède un nom d'utilisateur unique. Mais lorsque les utilisateurs ajoutent des articles de blog à l'application, nous utilisons une requête POST pour générer automatiquement une clé pour chaque article de blog :

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

Notre chemin posts contient désormais les données suivantes :

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

Notez que la clé -JSOpn9ZC54A4P4RoqVa a été automatiquement générée pour nous car nous avons utilisé une requête POST . Une requête réussie sera indiquée par un code d'état HTTP 200 OK , et la réponse contiendra la clé des nouvelles données ajoutées :

{"name":"-JSOpn9ZC54A4P4RoqVa"}

Suppression de données

Pour supprimer des données de la base de données, nous pouvons envoyer une demande DELETE avec l'URL du chemin à partir duquel nous souhaitons supprimer les données. Ce qui suit supprimerait Alan du chemin de nos users :

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

Une demande DELETE réussie sera indiquée par un code d'état HTTP 200 OK avec une réponse contenant JSON null .

Paramètres d'URI

L'API REST accepte les paramètres URI suivants lors de l'écriture de données dans la base de données :

authentification

Le paramètre de demande auth permet d'accéder aux données protégées par les règles de sécurité de la base de données en temps réel Firebase et est pris en charge par tous les types de requêtes. L'argument peut être soit le secret de notre application Firebase, soit un jeton d'authentification, que nous aborderons dans la section Autorisation de l'utilisateur . Dans l'exemple suivant, nous envoyons une requête POST avec un paramètre auth , où CREDENTIAL est soit le secret de notre application Firebase, soit un jeton d'authentification :

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

imprimer

Le paramètre print nous permet de préciser le format de notre réponse depuis la base de données. L'ajout print=pretty à notre demande renverra les données dans un format lisible par l'homme. print=pretty est pris en charge par les requêtes GET , PUT , POST , PATCH et DELETE .

Pour supprimer la sortie du serveur lors de l'écriture des données, nous pouvons ajouter print=silent à notre requête. La réponse résultante sera vide et indiquée par un code d'état HTTP 204 No Content si la demande aboutit. Le print=silent est pris en charge par les requêtes GET , PUT , POST et PATCH .

Écriture des valeurs du serveur

Les valeurs du serveur peuvent être écrites à un emplacement à l'aide d'une valeur d'espace réservé, qui est un objet avec une seule clé ".sv" . La valeur de cette clé est le type de valeur de serveur que nous souhaitons définir. Par exemple, pour définir un horodatage lors de la création d'un utilisateur, nous pourrions procéder comme suit :

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

"timestamp" est la seule valeur de serveur prise en charge et correspond au temps écoulé depuis l'époque UNIX en millisecondes.

Améliorer les performances d'écriture

Si nous écrivons de grandes quantités de données dans la base de données, nous pouvons utiliser le paramètre print=silent pour améliorer nos performances d'écriture et réduire l'utilisation de la bande passante. Dans le comportement d'écriture normal, le serveur répond avec les données JSON qui ont été écrites. Lorsque print=silent est spécifié, le serveur ferme immédiatement la connexion une fois les données reçues, réduisant ainsi l'utilisation de la bande passante.

Dans les cas où nous faisons de nombreuses requêtes à la base de données, nous pouvons réutiliser la connexion HTTPS en envoyant une requête Keep-Alive dans l'en-tête HTTP.

Conditions d'erreur

L'API REST renverra des codes d'erreur dans les circonstances suivantes :

Codes d'état HTTP
400 requêtes incorrectes

L'une des conditions d'erreur suivantes :

  • Impossible d'analyser les données PUT ou POST .
  • Données PUT ou POST manquantes.
  • La requête tente de PUT ou POST des données trop volumineuses.
  • L'appel d'API REST contient des noms d'enfants non valides dans le chemin.
  • Le chemin d'appel de l'API REST est trop long.
  • La requête contient une valeur de serveur non reconnue.
  • L'index de la requête n'est pas défini dans vos règles de sécurité de la base de données en temps réel Firebase .
  • La demande ne prend pas en charge l'un des paramètres de requête spécifiés.
  • La requête mélange les paramètres de requête avec une requête GET superficielle.
401 Non autorisé

L'une des conditions d'erreur suivantes :

404 introuvable La base de données Firebase spécifiée est introuvable.
500 Erreur de serveur interne Le serveur a renvoyé une erreur. Voir le message d'erreur pour plus de détails.
503 Service Indisponible La base de données Firebase Realtime spécifiée est temporairement indisponible, ce qui signifie que la demande n'a pas été tentée.

Sécuriser les données

Firebase dispose d'un langage de sécurité qui nous permet de définir quels utilisateurs ont un accès en lecture et en écriture aux différents nœuds de nos données. Vous pouvez en savoir plus à ce sujet dans Règles de sécurité des bases de données en temps réel .

Maintenant que nous avons abordé la sauvegarde des données, nous pouvons apprendre comment récupérer nos données de la base de données Firebase via l'API REST dans la section suivante.