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ć!)..equalTo('comedy')
zamiast.startAt('comedy').endAt('comedy')
?Napisałem osobistą bibliotekę, która pozwala zamawiać według wielu wartości, z całą kolejnością na serwerze.
Poznaj Querybase!
Querybase pobiera odwołanie do bazy danych Firebase i tablicę pól, które chcesz indeksować. Po utworzeniu nowych rekordów automatycznie obsłuży generowanie kluczy, które umożliwiają wielokrotne zapytania. Zastrzeżenie polega na tym, że obsługuje tylko prostą równoważność (nie mniejszą niż lub większą niż).
źródło
źródło
Odpowiedź Franka jest dobra, ale
array-contains
ostatnio wprowadzono Firestore, który ułatwia wykonywanie zapytań ORAZ.Możesz utworzyć
filters
pole, aby dodać filtry. Możesz dodać tyle wartości, ile potrzebujesz. Na przykład, aby filtrować według komedii i Jacka Nicholsona , możesz dodać wartość,comedy_Jack Nicholson
ale jeśli chcesz także według komedii i 2014 , możesz dodać wartośćcomedy_2014
bez tworzenia większej liczby pól.źródło
Firebase nie zezwala na zapytania z wieloma warunkami. Znalazłem jednak sposób na to:
Musimy pobrać początkowe przefiltrowane dane z bazy danych i przechowywać je na liście tablic.
Po uzyskaniu początkowych przefiltrowanych danych z bazy danych musimy wykonać dalsze filtrowanie w naszym backendie.
źródło
To zadziała.
źródło