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"
22
demandé sur Frank van Puffelen 2015-11-24 15:34:30

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.

66
répondu Frank van Puffelen 2015-11-24 15:12:20

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
}

entrez la description de l'image ici

--

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
}

entrez la description de l'image ici

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

13
répondu user2875289 2016-12-08 08:02:04

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

1
répondu Renan Coelho 2018-05-30 13:33:21

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;      
     } 
}];
0
répondu Muhammed Tanrıverdi 2017-07-11 11:01:47