Utilizzando l'API Query di Firebase , potresti essere tentato di provare questo:
// !!! THIS WILL NOT WORK !!!
ref
.orderBy('genre')
.startAt('comedy').endAt('comedy')
.orderBy('lead') // !!! THIS LINE WILL RAISE AN ERROR !!!
.startAt('Jack Nicholson').endAt('Jack Nicholson')
.on('value', function(snapshot) {
console.log(snapshot.val());
});
Ma come dice @RobDiMarco di Firebase nei commenti:
più orderBy()
chiamate genereranno un errore
Quindi il mio codice sopra non funzionerà .
Conosco tre approcci che funzioneranno.
1. filtrare la maggior parte sul server, fare il resto sul client
Quello che puoi fare è eseguirne uno orderBy().startAt()./endAt()
sul server, estrarre i dati rimanenti e filtrarli nel codice JavaScript sul tuo client.
ref
.orderBy('genre')
.equalTo('comedy')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
if (movie.lead == 'Jack Nicholson') {
console.log(movie);
}
});
2. aggiungere una proprietà che combina i valori su cui si desidera filtrare
Se ciò non è abbastanza buono, dovresti considerare di modificare / espandere i tuoi dati per consentire il tuo caso d'uso. Ad esempio: puoi inserire genere + lead in una singola proprietà che usi solo per questo filtro.
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_lead": "comedy_Jack Nicholson"
},...
In sostanza stai costruendo il tuo indice multi-colonna in quel modo e puoi interrogarlo con:
ref
.orderBy('genre_lead')
.equalTo('comedy_Jack Nicholson')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
David East ha scritto una libreria chiamata QueryBase che aiuta a generare tali proprietà .
Potresti anche fare query relative / intervallo, supponiamo che tu voglia consentire l'interrogazione di film per categoria e anno. Utilizzeresti questa struttura di dati:
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_year": "comedy_1997"
},...
E poi cerca commedie degli anni '90 con:
ref
.orderBy('genre_year')
.startAt('comedy_1990')
.endAt('comedy_2000')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
Se è necessario filtrare più di un solo anno, assicurarsi di aggiungere le altre parti della data in ordine decrescente, ad es "comedy_1997-12-25"
. In questo modo l'ordinamento lessicografico che Firebase esegue sui valori di stringa sarà lo stesso dell'ordinamento cronologico.
Questa combinazione di valori in una proprietà può funzionare con più di due valori, ma è possibile eseguire solo un filtro intervallo sull'ultimo valore nella proprietà composita.
Una variante molto speciale di questo è implementata dalla libreria GeoFire per Firebase . Questa libreria combina la latitudine e la longitudine di un luogo in un cosiddetto Geohash , che può quindi essere utilizzato per eseguire query di portata in tempo reale su Firebase.
3. creare un indice personalizzato a livello di codice
Un'altra alternativa è fare ciò che abbiamo fatto tutti prima dell'aggiunta di questa nuova API Query: creare un indice in un nodo diverso:
"movies"
// the same structure you have today
"by_genre"
"comedy"
"by_lead"
"Jack Nicholson"
"movie1"
"Jim Carrey"
"movie3"
"Horror"
"by_lead"
"Jack Nicholson"
"movie2"
Probabilmente ci sono più approcci. Ad esempio, questa risposta evidenzia un indice personalizzato alternativo a forma di albero: https://stackoverflow.com/a/34105063
orderBy()
chiamate genereranno un errore, poiché i client attualmente forniscono risultati imprevisti. È possibile che abbia funzionato casualmente nel tuo test, ma non è stato progettato per funzionare in modo generico (anche se ci piacerebbe aggiungerlo!).