orderByChild ne fonctionne pas dans Firebase
J'essaie d'interroger ma base de données de sorte qu'elle récupère une liste ordonnée basée sur une clé enfant. Je le fais comme suit (voir ci-dessous), mais rien ne se passe, ce qui signifie qu'il retourne un objet ordonné exactement de la même manière qu'il est stocké dans la base de données Firebase. Ce qui se passe?
self.getAllProfiles = function () {
var qProfile = $q.defer();
var ref = new Firebase(FBURL);
ref.child("users").orderByChild('last_update').on("value", function (snapshot) {
console.log(snapshot.val()) // HERE IS WHERE IT SHOULD BE ORDERED
qProfile.resolve(snapshot.val());
}, function (errorObject) {
qProfile.reject(errorObject);
});
return qProfile.promise;
};
Pour ajouter, mon nœud utilisateurs ressemble à ceci:
users
/$username
/last_update
/id
/data
/profile_image
/display_name
Voici un instantané:
Tester: Object
github: Object
last_update: 1447732462170
userId: "github:12345"
4 réponses
Lorsque vous appelez snapshot.val()
, vous récupérez un objet JSON. L'ordre des clés dans un objet JSON est déterminé par votre navigateur et non par Firebase.
Pour mettre les enfants en ordre:
self.getAllProfiles = function () {
var qProfile = $q.defer();
var ref = new Firebase(FBURL);
ref.child("users").orderByChild('last_update').on("value", function (snapshot) {
snapshot.forEach(function(child) {
console.log(child.val()) // NOW THE CHILDREN PRINT IN ORDER
});
qProfile.resolve(snapshot.val());
}, function (errorObject) {
qProfile.reject(errorObject);
});
return qProfile.promise;
};
, Vous pouvez laisser le q.resolve()
appel où il est: snapshot.forEach()
n'est pas un appel asynchrone.
Je sais que cette question a été répondue et a plus de 1 an, mais comme il y a encore une certaine confusion dans la section des commentaires, je voudrais ajouter quelques informations.
Le problème
Le problème d'origine est que L'OP veut récupérer une liste ordonnée basée sur une clé enfant de la base de données Firebase realtime, mais le .orderByChild('arg')
ne fonctionne pas comme prévu.
, Mais ce qui n'a pas fonctionné comme prévu, c'est pas .orderByChild('arg')
, mais .on("value", callback)
. Parce que .on("value", callback)
fonctionne un peu différent de d'autres types d'événements comme .on("child_added", callback)
.
Exemple
Disons que nous avons une base de données firebase en temps réel comme ci-dessous:
{
myData: {
-KYNMmYHrzLcL-OVGiTU: {
NO: 1,
image: ...
},
-KYNMwNIz4ObdKJ7AGAL: {
NO: 2,
image: ...
},
-KYNNEDkLpuwqQHSEGhw: {
NO: 3,
image: ...
},
}
}
--
Si nous utilisons .on("value", callback)
, le callback() sera appelé 1 fois et retournera un tableau D'objets de 3 objets.
ref.on("value", function(snapshot) {
console.log(snapshot.val());
// Please see Frank van Puffelen's answer
}
--
Si nous utilisons .on("child_added", callback)
, le callback() sera appelé 3 fois, chaque fois retourne un objet, et ils sont retournés dans commande.
ref.once("child_added", function(snapshot) {
console.log(snapshot.val());
// The objects are returned in order, do whatever you like
}
Conclusion
Si vous avez seulement besoin de récupérer les données ordonnées de firebase (par exemple pour initialiser L'interface utilisateur.) Alors ref.orderByChild('arg').once("child_added", callback)
vous convient bien, c'est simple et facile à utiliser.
Cependant, si pour une raison quelconque vous devez utiliser ref.orderByChild('arg').on("value", callback)
, veuillez consulter la réponse de Frank van Puffelen.
Référence
Veuillez lire document Firebase pour plus d'informations sur on(eventType, callback, cancelCallbackOrContext, context)
, leurs arguments et leur retour valeur.
Un Autre document utile: Travailler avec des Listes de Données sur le Web
Pour commander à l'aide de l'écouteur d'événement value
:
firebase.database().ref('/invoices').orderByChild('name').on('value', snapshot => {
snapshot.forEach(child => {
console.log(child.key, child.val());
});
}
, Si vous voulez inverser l'ordre, essayez:
function reverseSnapshotOrder (snapshot) {
let reversed = [];
snapshot.forEach(child => {
reversed.unshift(child);
});
return reversed;
}
reverseSnapshotOrder(snapshot).forEach(child => {
console.log(child.key, child.val());
});
, Veuillez consulter: https://firebase.google.com/docs/database/web/lists-of-data#listen_for_value_events
J'ai lutté avec le même problème dans iOS. Si vous convertissez l'instantané en objet NSDictionary, il se convertit en liste non ordonnée. Version Objective-c en cas de besoin:
[[self.refChild queryOrderedByChild:@"date_created"]
observeEventType:FIRDataEventTypeValue
withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
for (FIRDataSnapshot *child in snapshot.children) {
NSDictionary *anObject = child.value;
NSString *aKey = child.key;
}
}];