Wenn Sie die Abfrage-API von Firebase verwenden , könnten Sie versucht sein, Folgendes zu versuchen:
// !!! 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());
});
Aber wie @RobDiMarco von Firebase in den Kommentaren sagt:
Bei mehreren orderBy()
Anrufen wird ein Fehler ausgegeben
Also meine obigen Code wird nicht funktionieren .
Ich kenne drei Ansätze, die funktionieren werden.
1. Filtern Sie am meisten auf dem Server, erledigen Sie den Rest auf dem Client
Sie können eine orderBy().startAt()./endAt()
auf dem Server ausführen , die verbleibenden Daten abrufen und diese in JavaScript-Code auf Ihrem Client filtern.
ref
.orderBy('genre')
.equalTo('comedy')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
if (movie.lead == 'Jack Nicholson') {
console.log(movie);
}
});
2. Fügen Sie eine Eigenschaft hinzu, die die Werte kombiniert, nach denen Sie filtern möchten
Wenn dies nicht gut genug ist, sollten Sie in Betracht ziehen, Ihre Daten zu ändern / zu erweitern, um Ihren Anwendungsfall zu ermöglichen. Zum Beispiel: Sie könnten Genre + Blei in eine einzelne Eigenschaft einfügen, die Sie nur für diesen Filter verwenden.
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_lead": "comedy_Jack Nicholson"
},...
Auf diese Weise erstellen Sie im Wesentlichen Ihren eigenen mehrspaltigen Index und können ihn abfragen mit:
ref
.orderBy('genre_lead')
.equalTo('comedy_Jack Nicholson')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
David East hat eine Bibliothek namens QueryBase geschrieben, die beim Generieren solcher Eigenschaften hilft .
Sie können sogar Relativ- / Bereichsabfragen durchführen. Angenommen, Sie möchten das Abfragen von Filmen nach Kategorie und Jahr zulassen. Sie würden diese Datenstruktur verwenden:
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_year": "comedy_1997"
},...
Und dann nach Komödien der 90er abfragen mit:
ref
.orderBy('genre_year')
.startAt('comedy_1990')
.endAt('comedy_2000')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
Wenn Sie mehr als nur das Jahr filtern müssen, stellen Sie sicher, dass Sie die anderen Datumsteile in absteigender Reihenfolge hinzufügen, z "comedy_1997-12-25"
. Auf diese Weise entspricht die lexikografische Reihenfolge, die Firebase für Zeichenfolgenwerte ausführt, der chronologischen Reihenfolge.
Diese Kombination von Werten in einer Eigenschaft kann mit mehr als zwei Werten arbeiten, Sie können jedoch nur einen Bereichsfilter für den letzten Wert in der zusammengesetzten Eigenschaft ausführen.
Eine ganz besondere Variante davon implementiert die GeoFire-Bibliothek für Firebase . Diese Bibliothek kombiniert den Breiten- und Längengrad eines Ortes zu einem sogenannten Geohash , mit dem dann Echtzeit-Bereichsabfragen in Firebase durchgeführt werden können.
3. Erstellen Sie programmgesteuert einen benutzerdefinierten Index
Eine weitere Alternative besteht darin, das zu tun, was wir alle getan haben, bevor diese neue Abfrage-API hinzugefügt wurde: Erstellen Sie einen Index in einem anderen Knoten:
"movies"
// the same structure you have today
"by_genre"
"comedy"
"by_lead"
"Jack Nicholson"
"movie1"
"Jim Carrey"
"movie3"
"Horror"
"by_lead"
"Jack Nicholson"
"movie2"
Es gibt wahrscheinlich mehr Ansätze. In dieser Antwort wird beispielsweise ein alternativer baumförmiger benutzerdefinierter Index hervorgehoben: https://stackoverflow.com/a/34105063
orderBy()
Anrufen ein Fehler ausgegeben, da die Clients derzeit unerwartete Ergebnisse liefern. Es ist möglich, dass es in Ihrem Test zufällig funktioniert hat, aber nicht dafür ausgelegt ist, dies generisch zu funktionieren (obwohl wir es gerne hinzufügen würden!).