orderByChild no funciona en Firebase

Estoy intentando consultar mi database para que recupere una list orderada basada en una key secundaria. Lo hago de la siguiente manera (ver a continuación), pero no sucede nada, lo que significa que devuelve un object orderado exactamente de la misma manera que se almacena en la database de Firebase. Que esta pasando?

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; }; 

Para agregar, mi nodo de usuarios se ve de la siguiente manera:

 users /$username /last_update /id /data /profile_image /display_name 

Aquí hay una instantánea:

 Tester: Object github: Object last_update: 1447732462170 userId: "github:12345" 

Cuando llama a snapshot.val() , está recuperando un object JSON. El order de las keys en un object JSON viene determinado por su browser y no por Firebase.

Para poner a los niños en order:

 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; }; 

Puede dejar la llamada q.resolve() donde está: snapshot.forEach() no es una llamada asincrónica.

Sé que esta pregunta ha sido respondida y tiene más de 1 año de antigüedad, pero como todavía hay confusión en la sección de comentarios, me gustaría agregar algo de información.

El problema

El problema original es que el OP desea recuperar una list orderada basada en una key secundaria de la database en time real de Firebase, pero el .orderByChild('arg') no funciona como se esperaba.

Pero lo que no funcionó como se esperaba no es .orderByChild('arg') , sino .on("value", callback) . Porque .on("value", callback) funciona un poco diferente de otros eventTypes como .on("child_added", callback) .

Ejemplo

Digamos que tenemos una database en time real firebase como a continuación:

 { myData: { -KYNMmYHrzLcL-OVGiTU: { NO: 1, image: ... }, -KYNMwNIz4ObdKJ7AGAL: { NO: 2, image: ... }, -KYNNEDkLpuwqQHSEGhw: { NO: 3, image: ... }, } } 

Si usamos .on("value", callback) llamada), se llamará a la callback () 1 vez y se devolverá una matriz de objects de 3 objects.

 ref.on("value", function(snapshot) { console.log(snapshot.val()); // Please see Frank van Puffelen's answer } 

enter image description here

Si usamos .on("child_added", callback) , se llamará a la callback () 3 veces, cada vez que devuelva un object, y se devolverán en order .

 ref.once("child_added", function(snapshot) { console.log(snapshot.val()); // The objects are returned in order, do whatever you like } 

enter image description here

Conclusión

Si solo necesita get datos orderados de Firebase (por ejemplo, para inicializar la interfaz de usuario), entonces ref.orderByChild('arg').once("child_added", callback) queda bien, es simple y fácil de usar.

Sin embargo, si por alguna razón necesita usar ref.orderByChild('arg').on("value", callback) , entonces vea la respuesta de Frank van Puffelen.

Referencia

Lea el documento de Firebase para get más información sobre on(eventType, callback, cancelCallbackOrContext, context) , sus arguments y sus valores de retorno.

Otro documento útil: trabajar con lists de datos en la Web

Luché con el mismo problema en iOS. Si convierte una instantánea a un object NSDictionary, se convierte en una list desorderada. Versión Objective-c en caso de necesidad:

 [[self.refChild queryOrdenetworkingByChild:@"date_created"] observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { for (FIRDataSnapshot *child in snapshot.children) { NSDictionary *anObject = child.value; NSString *aKey = child.key; } }];