2016-06-24 23 views
11

Diciamo che ho alcuni dati come segue:Come posso impaginare in ordine decrescente per valore figlio con firebase?

{ 
    "name": "post #1", 
    "votes": 100 
}, 
{ 
    "name": "post #2", 
    "votes": 10000 
}, 
{ 
    "name": "post #3", 
    "votes": 750 
} 

E così via.

I dati in firebase non sono ordinati per voti, ovviamente, è per ordine.

Mi piacerebbe essere in grado di impaginare questi dati per il numero di voti in ordine decrescente.

penso che avrei dovuto fare qualcosa di simile:

ref.orderByChild('votes') 
    .startAt(someValue) 
    .limitToFirst(someOtherValue) 
    .once('value', function(snapshot) { 
     resolve(snapshot); 
    }); 

O forse, avrei bisogno di usare limitToLast, e endAt?

L'impaginazione di key è abbastanza semplice, ma questo mi ostacola.

Aggiornamento (2017/10/16): Firebase recentemente annunciato Firestore - proprio archivio dati NoSQL completamente gestito che dovrebbe rendere più facile fare query più complesse. Ci possono essere ancora alcuni casi d'uso in cui si potrebbe usare il database Realtime che hanno sempre fornito. Se sei una di quelle persone questa domanda dovrebbe ancora essere applicata.

+0

Vedere http://stackoverflow.com/questions/27195851/how-to-retrieve-paginated-children-in-ascending-or-descending-order-in-firebase/33484784#33484784 –

+0

@FrankvanPuffelen Il tuo collegamento è per una domanda che poi ricollega alla mia risposta qui sotto. Ragazzi, considerate di aggiungere queste informazioni ai documenti di Firebase? –

risposta

23

Ho postato questa domanda dopo una lunga giornata di programmazione e il mio cervello era in poltiglia.

Questa mattina ho fatto un altro tentativo e, come spesso accade, sono riuscito a trovare la soluzione piuttosto rapidamente.

Soluzione:

Per impaginare i dati, abbiamo bisogno della capacità di tirare arbitrariamente dati ordinati dalla metà di una lista. È possibile farlo utilizzando le seguenti funzioni fornite dalla API Firebase:

startAt

endAt

limitToFirst

limitToLast

Maggiori informazioni possono essere trovate here.

Nel mio caso, poiché ho bisogno dei miei dati in ordine decrescente, userò endAt e limitToLast.

Supponendo che mi piacerebbe che ciascuna delle mie pagine avesse cinque articoli. Vorrei scrivere la mia prima domanda in questo modo:

ref.orderByChild('votes') 
    .limitToLast(5) 
    .once('value', function(snapshot) { 
     console.log('Snap: ', snapshot.val()); 
    }); 

Questo ottiene i 5 elementi con il più alto numero di voti.

Per ottenere la pagina successiva, è necessario memorizzare due pezzi di dati dai risultati della nostra ultima query.Dobbiamo memorizzare il numero di voti e la chiave per l'articolo con il minor numero di voti. Vale a dire, l'ultimo elemento nella nostra lista.

Utilizzando questi dati, il nostro prossimo query e tutte le query successive, si presenteranno come segue:

ref.orderByChild('votes') 
    .endAt(previousVoteCount, previousKey) 
    .limitToLast(5) 
    .once('value', function(snapshot) { 
     console.log('Snap: ', snapshot.val()); 
    }); 

Noterete in questa interrogazione ho aggiunto endAt. Questo ottiene i prossimi 5 elementi con il maggior numero di voti a partire dall'ultimo nell'elenco precedente. Dobbiamo includere la chiave per l'ultimo elemento nell'elenco precedente in modo che se ci sono più elementi con lo stesso numero di voti, verrà restituito un elenco che inizia con l'elemento corretto, e non il primo che trova con quel numero di voti, che potrebbe essere da qualche parte nel mezzo della lista che hai ottenuto dalla query iniziale.

Questo è tutto!

+0

Questa soluzione funziona con molti articoli con lo stesso valore? Per esempio seguenti punteggi: [5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7]. In uno scenario reale, non molti post votati in alto condivideranno lo stesso valore, ma un sacco di valori di basso punteggio lo faranno. Questo problema è commentato nella mia domanda SO evidenziata da @ frank-van-puffelen sopra. – Pandaiolo

+0

Supponendo che tu stia memorizzando i tuoi dati in un unico elenco con le chiavi firebase, la parte orderByChild della query verrà ordinata per 'voti' prima, quindi se ci saranno molti messaggi con lo stesso numero di voti, ordinerà per chiave. –

+1

Ciò significa che se si include l'argomento "previousKey" nella parte "endAt" della query, sarà possibile eseguire il paginamento in modo accurato. –

Problemi correlati