2015-11-24 14 views
15

Sto cercando di interrogare il mio database in modo tale che recuperi un elenco ordinato basato su una chiave figlio. Lo faccio come segue (vedi sotto), ma non succede nulla, nel senso che restituisce un oggetto ordinato esattamente nello stesso modo in cui è memorizzato nel database Firebase. Cosa sta succedendo?orderByChild non funziona in Firebase

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

Per aggiungere, il mio nodo utenti appare come segue:

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

Ecco un'istantanea:

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

Puoi mostrare i tuoi dati in modo non ordinato e come appare quando ritorna come un'istantanea? –

+0

È stata aggiornata la domanda con lo snapshot – JohnAndrews

+1

È difficile dire cosa sta succedendo con i dati forniti. Puoi creare un JSBin che mostri il tuo problema? Ciò renderebbe molto più semplice la risoluzione di ciò che sta accadendo. –

risposta

54

Quando si chiama snapshot.val(), si stanno ottenendo indietro un oggetto JSON. L'ordine delle chiavi in ​​un oggetto JSON è determinato dal tuo browser e non da Firebase.

per ottenere i bambini per:

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

È possibile lasciare la q.resolve() chiamata dove si trova: snapshot.forEach() non è una chiamata asincrona.

+13

Quindi se abbiamo bisogno dei dati ordinati dobbiamo creare un nuovo oggetto con nuove chiavi o mettere ogni child.val() in una matrice. Non è terribilmente inefficiente? – Pier

+4

Ti dispiacerebbe rispondere alla domanda di @Pier? Ho la stessa domanda. – Onichan

+1

@Pier Non è necessario se si utilizzano altri tipi di evento, vedere la risposta per i dettagli. – user2875289

11

So che questa domanda ha avuto una risposta ed è più vecchia di un anno, ma poiché nella sezione commenti c'è ancora confusione, vorrei aggiungere alcune informazioni.

Il problema

Il problema originale è che il PO vuole recuperare un elenco ordinato in base a una chiave bambino da base di dati in tempo reale Firebase, ma il .orderByChild('arg') non funziona come previsto.

Ma ciò che non ha funzionato come previsto non è .orderByChild('arg'), ma .on("value", callback). Perché .on("value", callback) funziona un po 'diverso da altri tipi di evento come .on("child_added", callback).

Esempio

Supponiamo di avere una base di dati in tempo reale Firebase come di seguito:

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

-

Se usiamo .on("value", callback), il callback() verrà chiamato 1 volta, e restituire un Matrice di oggetti di 3 oggetti.

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

enter image description here

-

Se usiamo .on("child_added", callback), il callback() sarà chiamato 3 volte, ogni volta restituisce un oggetto, e sono restituiti al fine.

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

enter image description here

Conclusione

Se avete solo bisogno di recuperare i dati ordinati da Firebase (ad esempio per inizializzare UI). Poi ref.orderByChild('arg').once("child_added", callback) vi si addice bene, è semplice e facile da usare.

Tuttavia, se per qualche motivo è necessario utilizzare ref.orderByChild('arg').on("value", callback), vedere la risposta di Frank van Puffelen.

Riferimento

Si prega di leggere Firebase Document per ulteriori informazioni su on(eventType, callback, cancelCallbackOrContext, context), i loro argomenti ei loro valori di ritorno.

Un altro documento utile: Work with Lists of Data on the Web

+1

La vera ragione per cui vedi la differenza è che il tipo di risultato della query FIB è 'dizionario' dove la 'chiave' (id) del record è la "chiave" del dizionario. Quindi, JS (browser) ordina questa lista per la sua chiave. Ecco perché se si esegue una query come "child_added" (uno per uno) o si utilizza "snapshot.forEach", si risolverà questo fenomeno. Quindi questo è più di cosa JS piuttosto che cosa FIB. La risposta di @ frank-van-puffelen è più corretta per questo motivo. –

+0

@EliLivshitz Totalmente d'accordo. – user2875289

0

ho lottato con lo stesso problema in iOS. Se si converte lo snapshot in oggetto NSDictionary, questo viene convertito in un elenco non ordinato. Versione Objective-C in caso di necessità:

[[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;  
    } 
}]; 
Problemi correlati