2014-11-28 18 views
8

Supponiamo che sto utilizzando Firebase per un sistema di commenti e voglio recuperare i commenti per un dato argomento, ma ci sono così tanti commenti in un argomento che non voglio recuperarli tutti in una volta. Voglio anche che i più recenti commenti vengano visualizzati in cima.Come recuperare i bambini impaginati in ordine ascendente o discendente in Firebase?

Sembra che l'unico modo per visualizzare i record di Firebase in ordine inverso è quello di recuperarli tutti e quindi scorrere su di essi al contrario.

Questo potrebbe diventare molto ingombrante su dataset di grandi dimensioni, in particolare per i client mobili.

C'è un modo migliore? Qual è la soluzione generica e preferita per interrogare i dati impaginati da Firebase, in ordine ascendente o discendente?

+0

"Sembra che l'unico modo per visualizzare i record Firebase in ordine inverso sia quello di recuperarli tutti e poi scorrere su di essi al contrario." Potresti voler rileggere la documenazione, in particolare su 'limite'. https://www.firebase.com/docs/web/guide/retrieving-data.html#section-queries –

+0

Grazie Frank, ero a conoscenza di quei documenti. La priorità può essere utilizzata per ordinare in diversi ordini, ma ho difficoltà a pensare a un modo efficace di impostare la priorità di un elemento in un modo che potrebbe essere ordinato in ordine cronologico inverso. Puoi? – cayblood

+1

Non solo per priorità, puoi ordinarlo oggigiorno da qualsiasi bambino usando 'orderByChild'. Leggi questo post del blog per aggiornarti: https://www.firebase.com/blog/2014-11-04-firebase-realtime-queries.html. Qualcosa come "orderByChild" seguito da "limitToLast" e quindi "Array.reverse" dovrebbe fare ciò che è necessario per te. –

risposta

11

risposta Aggiornato

@Tyler rispondere stackoverflow.com/a/38024909/681290 è una più aggiornata e la risposta più conveniente per questa domanda

TL; DR

Non c'è soluzione se quello che stanno cercando di fare è:

ref.orderBy(field, 'DESC').offset(n).limit(x) 

Inoltre, nel github di Firebase sono presenti strumenti non supportati that do pagination, sebbene solo nell'ordine ascendente solo.

Altrimenti, qui ci sono le soluzioni più vicine possibili, che ho trovato io stesso, o sul web finora. Ho deliberatamente interpretato la domanda come generica, non solo sui campi temporali come richiesto dall'OP.


Utilizzare priorità

L'obiettivo è quello di utilizzare setWithPriority() e setPriority() sui bambini per essere in grado di ottenere i dati ordinati in seguito con orderByPriority().

Issues:

  • non vedo il vantaggio rispetto utilizzando un indicizzato priority campo, invece? (In realtà, la priorità viene memorizzato come un campo sottostante chiamato .priority, che si può vedere quando l'esportazione dei dati JSON)
  • difficile da mantenere per molti casi d'uso, per determinare il valore di priorità per impostare

campi bambino ridondante con dati negativi

per esempio, possiamo usare un timestamp timeRev campo indicizzato negativo in aggiunta a time essere in grado di ottenere gli elementi più recenti.

ref.orderByChild('timeRev') 
    .limitToFirst(100); 

Issues:

  • aggiunge ulteriore complessità al app: campi aggiuntivi devono essere mantenuti
  • può rompere atomicità del campo (ad esempio un campo score può essere aggiornato in una sola volta, Non sono sicuro se sia possibile con due campi, uno positivo e uno negativo)
  • Penso che questa soluzione alternativa sia stata utilizzata quando c'era solo limit() nell'API Firebase, ma è un po 'obsoleto ora che possiamo usare limitToFist(), limitToLast(), e la gamma di query (vedi sotto)

Utilizzando limitToLast() e endAt() gamma query

Questo Evitiamo campo negativo e ridondante:

ref.orderBy('time') 
    .limitToLast(100) 

Questo dovrebbe essere piuttosto efficace con i campi di timestamp, perché di solito questo è un campo unico.

L'array risultante di elementi deve semplicemente essere invertito prima dell'uso. (Basta ricordare Array.prototype.reverse() è mutevole, in modo che cambierà la vostra array)

Issues:

  • la documentazione API dicono che solo il valore della chiave ordinata può essere impostato come un startAt o endAt confine. Se molti articoli condividono lo stesso valore, il set di dati non può essere suddiviso in offset di lunghezza fissa.

Esempio con i seguenti elementi in possesso di un valore di score:

{ 
    items: { 
    a: {score: 0}, 
    b: {score: 0}, 
    c: {score: 1}, 
    d: {score: 1}, 
    e: {score: 2}, 
    f: {score: 5} 
    } 
} 

prima query pagina per ottenere i migliori elementi di punteggio:

ref.child('items').orderByChild('score') 
    .limitToLast(3) 

risultati:

{ 
    d: {score: 1}, 
    e: {score: 2}, 
    f: {score: 5} 
} 

Nota il primo elemento del sottoinsieme h come una partitura 1, quindi cerchiamo di ottenere la pagina precedente selezionando tutte le voci con punteggio di 1 o meno:

ref.child('items').orderByChild('score') 
    .endAt(1) 
    .limitToLast(3) 

Con tale query, otteniamo b,c,d articoli, invece di a,b,c elementi, che si prevede come da i documenti API, dato il numero endAt(1), sono comprensivi, quindi cercherà di ottenere tutti i punteggi di 1 e non ha modo di ordinare quelli che sono già stati restituiti in precedenza.

Soluzione

Questo può essere attenuato non aspettati ogni sottoinsieme di tenere la stessa quantità di record e scartando quelle già caricato.

Ma, se il primo milione di utenti della mia app hanno un punteggio 0, questo sottoinsieme non può essere impaginato, perché il endAt offset è inutile, in quanto si basa sul valore invece del numero di record.

non vedo alcuna soluzione per questo caso d'uso, immagino Firebase non è destinato a questo :-)

Edit: Alla fine, io sto usando Algolia per tutti gli usi di ricerca-correlato. È un'API davvero carina, e spero che Google finisca per acquisire Algolia per integrare sia Firebase & Algolia, in quanto la loro complementarità è vicina al 100%! Disclaimer: nessuna proprietà posseduta !! :-)

+1

Questo mi sta facendo impazzire, in ordine inverso non posso ottenere elementi per la mia pagina 2. Supponiamo di avere 100 elementi per pagina, è facile ottenere la prima pagina con 'limitToLast' 100 e array inverso. Ora come ottengo la seconda pagina? Le mie chiavi sono chiavi generate da Firebase '-Jp9p7glAp98TMYBOcig' ecc. Solo se Firebase mi darà il numero totale di elementi in un nodo senza tirarne fuori tutto, sarebbe un gioco da ragazzi. Ho 117k elementi in un nodo e pesa 25mb (con poco profondo 3mb), quindi non è una soluzione. – Skyzer

+0

Vorrei che ci fosse 'startAt' /' endAt' in combinazione con il limite per recuperare il numero specifico di elementi. Quindi potrebbe essere fatto con la prima pagina usando 'limitToLast' 100 + 1 elementi e quindi usando la chiave elemento 101st per ottenere elementi 101-200 con' endAt = 101st element' e limitando il risultato per 100 elementi. – Skyzer

+0

Il contenuto 'starAt' * deve * corrispondere a' orderBy'. per esempio in ordine inverso: '.orderByKey(). endAt (lastKnownKey) .limitToLast (100)'. * Modifica: sembra che sia quello che stai facendo ... beh, funziona per me:) * – Pandaiolo

Problemi correlati