Korzystając z interfejsu API zapytań Firebase , możesz ulec pokusie wypróbowania:
// !!! 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());
});
Ale jak mówi @RobDiMarco z Firebase w komentarzach:
wiele orderBy()
połączeń spowoduje zgłoszenie błędu
Więc mój powyższy kod nie zadziała .
Znam trzy podejścia, które się sprawdzą.
1. Filtruj najwięcej na serwerze, resztę wykonaj na kliencie
Co można zrobić, to wykonać jeden orderBy().startAt()./endAt()
na serwerze, należy pociągnąć w dół pozostałe dane i filtr, który w kodzie JavaScript na kliencie.
ref
.orderBy('genre')
.equalTo('comedy')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
if (movie.lead == 'Jack Nicholson') {
console.log(movie);
}
});
2. dodaj właściwość, która łączy wartości, według których chcesz filtrować
Jeśli to nie wystarczy, powinieneś rozważyć modyfikację / rozszerzenie danych, aby umożliwić przypadek użycia. Na przykład: możesz umieścić gatunek + ołów w jednej właściwości, której używasz tylko dla tego filtra.
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_lead": "comedy_Jack Nicholson"
},...
Zasadniczo budujesz w ten sposób własny indeks wielokolumnowy i możesz wyszukiwać go za pomocą:
ref
.orderBy('genre_lead')
.equalTo('comedy_Jack Nicholson')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
David East napisał bibliotekę o nazwie QueryBase, która pomaga w generowaniu takich właściwości .
Możesz nawet wykonywać zapytania dotyczące zakresu / zakresu, powiedzmy, że chcesz zezwolić na wyszukiwanie filmów według kategorii i roku. Użyłbyś tej struktury danych:
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_year": "comedy_1997"
},...
A potem zapytanie o komedie z lat 90. z:
ref
.orderBy('genre_year')
.startAt('comedy_1990')
.endAt('comedy_2000')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
Jeśli chcesz filtrować według więcej niż tylko roku, pamiętaj, aby dodać inne części daty w kolejności malejącej, np "comedy_1997-12-25"
. W ten sposób uporządkowanie leksykograficzne, które Firebase wykonuje dla wartości ciągu, będzie takie samo, jak uporządkowanie chronologiczne.
To połączenie wartości we właściwości może działać z więcej niż dwiema wartościami, ale można wykonać filtr zakresu tylko na ostatniej wartości we właściwości złożonej.
Bardzo szczególny wariant tego jest realizowany przez bibliotekę GeoFire dla Firebase . Ta biblioteka łączy szerokość i długość geograficzną lokalizacji w tak zwany Geohash , który można następnie wykorzystać do wykonywania zapytań o zasięg w czasie rzeczywistym na Firebase.
3. Utwórz programowo indeks niestandardowy
Jeszcze inną alternatywą jest zrobienie tego, co wszyscy zrobiliśmy przed dodaniem tego nowego interfejsu API zapytań: utwórz indeks w innym węźle:
"movies"
// the same structure you have today
"by_genre"
"comedy"
"by_lead"
"Jack Nicholson"
"movie1"
"Jim Carrey"
"movie3"
"Horror"
"by_lead"
"Jack Nicholson"
"movie2"
Prawdopodobnie jest więcej podejść. Na przykład ta odpowiedź podkreśla alternatywny indeks niestandardowy w kształcie drzewa: https://stackoverflow.com/a/34105063
orderBy()
połączeń spowoduje zgłoszenie błędu, ponieważ klienci dają obecnie nieoczekiwane wyniki. Możliwe, że przypadkowo zadziałało to w teście, ale nie zostało zbudowane tak, aby działało ogólnie (choć chcielibyśmy to dodać!).