Ce document couvre les bases de la récupération des données de base de données, comment les données sont ordonnées et comment effectuer des requêtes simples sur les données. La récupération des données dans le SDK Admin est implémentée de façon légèrement différente selon langages de programmation.
- Écouteurs asynchrones: Les données stockées dans un Firebase Realtime Database sont récupérées en attachant un écouteur asynchrone à un de base de données. L'écouteur est déclenché une fois pour l'état initial des données, puis chaque fois que les données changent. Un écouteur d'événements peut recevoir plusieurs types d'événements. Ce mode de récupération des données est pris en charge dans les SDK Admin Java, Node.js et Python.
- Lectures bloquantes : les données stockées dans un Firebase Realtime Database sont récupérées en appelant une méthode bloquante sur une référence de base de données, qui renvoie les données stockées à la référence. Chaque appel de méthode est opération. Cela signifie que le SDK n'enregistre aucun rappel qui écoute les mises à jour de données ultérieures. Ce modèle de récupération de données est compatible avec les SDK Python et Go Admin.
Premiers pas
Reprenons l'exemple de blog de l'article précédent pour comprendre comment lire les données d'une base de données Firebase. Rappel que les articles de blog de l'application exemple sont stockés à l'URL de la base de données https://docs-examples.firebaseio.com/server/saving-data/fireblog/posts.json. Pour lire les données de vos posts, procédez comme suit:
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())
Accéder
// 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) }
Si vous exécutez le code ci-dessus, vous verrez un objet contenant tous vos messages enregistrés dans la console. Dans le cas de Node.js et Java, la fonction d'écouteur est appelée chaque fois que de nouvelles données sont ajoutées à la référence de votre base de données. Vous n'avez pas besoin d'écrire de code supplémentaire pour y parvenir.
En Java et Node.js, la fonction de rappel reçoit un DataSnapshot
, qui est un instantané des données. Un instantané est une image des données d'une référence de base de données spécifique à un moment donné. L'appel de val()
/ getValue()
sur un instantané renvoie la représentation d'un objet propre à la langue des données. S'il n'existe aucune donnée à l'emplacement de la référence, la valeur de l'instantané est null
. La méthode get()
de Python renvoie directement une représentation Python des données. Dans Go, la fonction Get()
désassemble les données dans une structure de données donnée.
Notez que nous avons utilisé le type d'événement value
dans l'exemple ci-dessus, qui lit l'intégralité du contenu d'une référence de base de données Firebase, même si une seule donnée a été modifiée. value
est l'un des cinq types d'événements différents listés ci-dessous, que vous pouvez utiliser pour lire des données depuis la base de données.
Lire les types d'événements en Java et Node.js
Valeur
L'événement value
permet de lire un instantané statique du contenu dans un chemin de base de données donné, car il existait au moment de l'événement de lecture. Il est déclenché une fois avec les données initiales, puis chaque fois que les données changent. Le rappel d'événement reçoit un instantané contenant toutes les données à cet emplacement, y compris les données enfants. Dans l'exemple de code ci-dessus, value
a renvoyé tous les articles de blog de votre application. Chaque fois qu'un nouvel article de blog est ajouté, la fonction de rappel renvoie tous les articles.
Enfant ajouté
L'événement child_added
est généralement utilisé lors de la récupération d'une liste d'éléments à partir de la base de données. Contrairement à value
, qui renvoie l'intégralité du contenu de l'emplacement, child_added
est déclenché une fois pour chaque enfant existant, puis à nouveau chaque fois qu'un nouvel enfant est ajouté au chemin spécifié. Le rappel d'événement reçoit un instantané contenant les données du nouvel enfant. À des fins de tri, un second argument contenant la clé de l'enfant précédent est également transmis.
Si vous souhaitez récupérer uniquement les données de chaque nouvel article ajouté à votre application de blog, vous pouvez utiliser 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); });
Dans cet exemple, l'instantané contiendra un objet avec un article de blog individuel. Étant donné que le SDK convertit les posts en objets en récupérant la valeur, vous avez accès aux propriétés "author" et "title" du post en appelant respectivement author
et title
. Vous avez également accès à l'ID de l'article précédent à partir du deuxième argument prevChildKey
.
Compte enfant modifié
L'événement child_changed
est déclenché chaque fois qu'un nœud enfant est modifié. Cela inclut les
les modifications apportées aux descendants du nœud enfant. Il est généralement utilisé avec child_added
.
et child_removed
pour répondre aux modifications apportées à une liste d'éléments. L'instantané transmis au rappel d'événement contient les données mises à jour pour l'enfant.
Vous pouvez utiliser child_changed
pour lire les données mises à jour sur les articles de blog lorsqu'ils sont modifiés:
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); });
Enfant supprimé
L'événement child_removed
est déclenché lorsqu'un enfant immédiat est supprimé. Il est généralement utilisé avec child_added
et child_changed
. L'instantané transmis au rappel d'événement contient les données de l'enfant supprimé.
Dans l'exemple du blog, vous pouvez utiliser child_removed
pour enregistrer dans la console une notification concernant l'article supprimé:
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'); });
Enfant déplacé
L'événement child_moved
est utilisé lorsque vous travaillez avec des données ordonnées, comme expliqué dans la section suivante.
Garanties d'événement
La base de données Firebase offre plusieurs garanties importantes concernant les événements:
Garanties concernant les événements de base de données |
---|
Les événements sont toujours déclenchés lorsque l'état local change. |
À terme, les événements refléteront toujours l'état correct des données, même dans les cas où les opérations ou les opérations locales de synchronisation provoque des différences temporaires, comme une perte temporaire de connexion réseau. |
Les écritures d'un seul client sont toujours écrites sur le serveur et diffusées aux autres utilisateurs dans l'ordre. |
Les événements de valeur sont toujours déclenchés en dernier et contiennent les mises à jour de tout autre événement survenu. avant la prise de cet instantané. |
Les événements de valeur étant toujours déclenchés en dernier, l'exemple suivant fonctionnera toujours:
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); });
Dissociation des rappels
Pour supprimer les rappels, spécifiez le type d'événement et la fonction de rappel à supprimer, comme suit:
Java
// Create and attach listener ValueEventListener listener = new ValueEventListener() { // ... }; ref.addValueEventListener(listener); // Remove listener ref.removeEventListener(listener);
Node.js
ref.off('value', originalCallback);
Si vous avez transmis un contexte de champ d'application à on()
, il doit l'être lors de la dissociation du rappel:
Java
// Not applicable for Java
Node.js
ref.off('value', originalCallback, ctx);
Si vous souhaitez supprimer tous les rappels d'un établissement, procédez comme suit:
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();
Lecture unique des données
Dans certains cas, il peut être utile qu'un rappel soit appelé une fois, puis supprimé immédiatement. Nous avons créé un assistant pour vous faciliter la tâche:
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())
Accéder
// 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) }
Interroger des données
Les requêtes de base de données Firebase vous permettent de récupérer des données de manière sélective en fonction de différents facteurs. Pour créer une requête dans votre base de données, vous devez commencer par spécifier le mode de classement de vos données à l'aide de l'une des fonctions de tri: orderByChild()
, orderByKey()
ou orderByValue()
. Vous pouvez ensuite les combiner avec cinq autres méthodes pour effectuer des requêtes complexes: limitToFirst()
,
limitToLast()
, startAt()
, endAt()
et equalTo()
.
Puisque toute l'équipe Firebase pense que les dinosaures sont plutôt cool, nous allons utiliser un extrait d'un exemple de base de données de faits sur les dinosaures pour vous montrer comment interroger des données dans votre base de données Firebase.
{ "lambeosaurus": { "height" : 2.1, "length" : 12.5, "weight": 5000 }, "stegosaurus": { "height" : 4, "length" : 9, "weight" : 2500 } }
Vous pouvez organiser les données de trois manières: par clé enfant, par clé ou par valeur. Une requête de base de données commence par l'une de ces fonctions de tri, chacune étant expliquée ci-dessous.
Trier par une clé enfant spécifiée
Vous pouvez classer les nœuds selon une clé enfant commune en transmettant cette clé à orderByChild()
. Par exemple, pour lire tous les dinosaures classés par taille, vous pouvez effectuer
les éléments suivants:
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))
Accéder
// 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) }
Tout nœud qui ne possède pas la clé enfant sur laquelle porte l'interrogation est trié avec la valeur null
, ce qui signifie qu'il apparaît en premier dans l'ordre. Pour en savoir plus sur l'ordre des données, consultez la section Mode de tri des données.
Les requêtes peuvent également être ordonnées par enfants profondément imbriqués, plutôt que par enfants seulement d'un niveau en dessous. Cela est utile si vous avez des données profondément imbriquées comme celles-ci:
{ "lambeosaurus": { "dimensions": { "height" : 2.1, "length" : 12.5, "weight": 5000 } }, "stegosaurus": { "dimensions": { "height" : 4, "length" : 9, "weight" : 2500 } } }
Pour interroger la hauteur maintenant, vous pouvez utiliser le chemin d'accès complet à l'objet plutôt qu'une seule clé:
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))
Accéder
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) }
Les requêtes ne peuvent être triées que selon une clé à la fois. Vous appelez orderByChild()
...
sur une même requête génère une erreur.
Trier par clé
Vous pouvez également trier les nœuds en fonction de leurs clés à l'aide de la méthode orderByKey()
. La
L'exemple suivant lit tous les dinosaures par ordre alphabétique:
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)
Accéder
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)
Trier par valeur
Vous pouvez trier les nœuds en fonction de la valeur de leurs clés enfants à l'aide de la méthode orderByValue()
. Supposons que les dinosaures participent à une compétition sportive et que vous teniez le score au format suivant :
{ "scores": { "bruhathkayosaurus" : 55, "lambeosaurus" : 21, "linhenykus" : 80, "pterodactyl" : 93, "stegosaurus" : 5, "triceratops" : 22 } }
Pour trier les dinosaures en fonction de leur score, vous pouvez construire la requête suivante:
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))
Accéder
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) }
Consultez la section Ordonnancement des données pour découvrir comment les valeurs null
, booléennes, de chaîne et d'objet sont triées lorsque vous utilisez orderByValue()
.
Requêtes complexes
Maintenant que vous savez comment vos données sont ordonnées, vous pouvez utiliser les méthodes limit ou range décrites ci-dessous pour créer des requêtes plus complexes.
Limiter les requêtes
Les requêtes limitToFirst()
et limitToLast()
permettent de définir un
nombre maximal d'enfants à synchroniser pour un rappel donné. Si vous définissez une limite de 100,
ne recevra initialement que 100 événements child_added
maximum. Si vous avez moins de 100 messages stockés dans votre base de données, un événement child_added
se déclenche pour chaque message. Toutefois, si vous avez plus de 100 messages, vous ne recevrez un événement child_added
que pour 100 d'entre eux. Il s'agit des 100 premiers messages ordonnés si vous utilisez
limitToFirst()
ou les 100 derniers messages ordonnés si vous utilisez
limitToLast()
Vous recevrez child_added
événements à mesure que les articles changent
pour les éléments qui entrent dans la requête et les événements child_removed
pour les éléments qui la quittent,
afin que le nombre
total reste à 100.
À l'aide de la base de données sur les informations sur les dinosaures et de orderByChild()
, vous pouvez trouver les deux dinosaures les plus lourds :
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)
Accéder
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()) }
Le rappel child_added
est déclenché exactement deux fois, sauf s'il existe
moins de deux dinosaures
stockés dans la base de données. Elle sera également déclenchée pour chaque nouveau dinosaure plus lourd ajouté à la base de données.
En Python, la requête renvoie directement un OrderedDict
contenant les deux dinosaures les plus lourds.
De même, vous pouvez trouver les deux dinosaures les plus courts à l'aide de 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)
Accéder
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()) }
Le rappel child_added
est déclenché exactement deux fois, sauf si moins de deux dinosaures sont stockés dans la base de données. Il sera également déclenché à nouveau si l'un des deux premiers dinosaures est supprimé de la base de données, car un nouveau dinosaure sera désormais le deuxième plus petit. En Python, la requête renvoie directement un OrderedDict
contenant les dinosaures les plus courts.
Vous pouvez également effectuer des requêtes de limite avec orderByValue()
. Si vous souhaitez créer un classement avec les trois dinosaures sportifs ayant obtenu le plus de points, vous pouvez procéder comme suit:
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))
Accéder
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) }
Requêtes de plage
L'utilisation de startAt()
, endAt()
et equalTo()
vous permet de :
choisir des points de départ et d'arrivée arbitraires pour vos requêtes. Par exemple, si vous souhaitez
trouver tous les dinosaures mesurant au moins trois mètres, vous pouvez combiner orderByChild()
et 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)
Accéder
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()) }
Vous pouvez utiliser endAt()
pour trouver tous les dinosaures dont le nom est antérieur au ptérodactyle.
lexicographiquement:
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)
Accéder
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()) }
Vous pouvez combiner startAt()
et endAt()
pour limiter les deux extrémités de votre
requête. L'exemple suivant trouve tous les dinosaures dont le nom commence par la lettre "b" :
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)
Accéder
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()) }
La méthode equalTo()
vous permet de filtrer en fonction de correspondances exactes. Comme c’est le cas
avec les autres requêtes de plage, il se déclenchera pour chaque nœud enfant correspondant. Par exemple, vous pouvez
utilisez la requête suivante pour trouver tous les dinosaures mesurant 25 mètres de haut:
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)
Accéder
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()) }
Les requêtes de plage sont également utiles lorsque vous devez paginer vos données.
Synthèse
Vous pouvez combiner toutes ces techniques pour créer des requêtes complexes. Par exemple, vous pouvez trouver le nom du dinosaure qui est juste plus court que stégosaure:
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')
Accéder
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") }
Comment les données sont-elles ordonnées
Cette section explique comment vos données sont ordonnées lorsque vous utilisez chacune des quatre fonctions de tri.
ordreParEnfant
Lorsque vous utilisez orderByChild()
, les données contenant la clé enfant spécifiée sont classées comme suit:
- Les enfants avec une valeur
null
pour la clé enfant spécifiée sont placés en premier. - Les enfants dont la valeur est
false
pour la clé enfant spécifiée sont les suivants. Si plusieurs enfants ont la valeurfalse
, ils sont triés de manière lexicographique par clé. - Les enfants dont la valeur de la clé enfant spécifiée est
true
viennent ensuite. Si plusieurs enfants ont une valeur detrue
, ils sont triés de manière lexicographique par clé. - Les enfants avec une valeur numérique arrivent ensuite, triés par ordre croissant. Si plusieurs enfants ont la même valeur numérique pour le nœud enfant spécifié, ils sont triés par clé.
- Les chaînes apparaissent après les nombres et sont triées de manière lexicographique par ordre croissant. Si plusieurs enfants ont la même valeur pour le nœud enfant spécifié, ils sont triés de façon lexicographique par clé.
- Les objets sont placés en dernier et triés par ordre croissant, par clé.
ordreParClé
Lorsque vous utilisez orderByKey()
pour trier vos données, elles sont renvoyées dans l'ordre croissant par clé, comme suit. N'oubliez pas que les clés ne peuvent être que des chaînes.
- Les enfants avec une clé pouvant être analysée en tant qu'entier 32 bits sont placés en premier, triés par ordre croissant.
- Les enfants avec une valeur de chaîne comme clé arrivent ensuite, triés de manière lexicographique par ordre croissant.
orderByValue
Lorsque vous utilisez orderByValue()
, les enfants sont triés en fonction de leur valeur. Les critères de tri sont les mêmes que dans orderByChild()
, sauf que la valeur du nœud est utilisée à la place de la valeur d'une clé enfant spécifiée.