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!)..equalTo('comedy')
statt verwenden.startAt('comedy').endAt('comedy')
?Ich habe eine persönliche Bibliothek geschrieben, in der Sie nach mehreren Werten bestellen können, wobei die gesamte Bestellung auf dem Server erfolgt.
Lernen Sie Querybase kennen!
Querybase enthält eine Firebase-Datenbankreferenz und ein Array von Feldern, auf die Sie indizieren möchten. Wenn Sie neue Datensätze erstellen, werden automatisch Schlüssel generiert, die mehrere Abfragen ermöglichen. Die Einschränkung ist, dass es nur eine gerade Äquivalenz unterstützt (nicht kleiner oder größer als).
quelle
quelle
Franks Antwort ist gut, aber Firestore wurde
array-contains
kürzlich eingeführt , was es einfacher macht, UND-Abfragen durchzuführen.Sie können ein
filters
Feld erstellen , um Ihre Filter hinzuzufügen. Sie können beliebig viele Werte hinzufügen. Wenn Sie beispielsweise nach Comedy und Jack Nicholson filterncomedy_Jack Nicholson
möchten, können Sie den Wert hinzufügen. Wenn Sie jedoch auch nach Comedy und 2014 filtern möchten, können Sie den Wert hinzufügen,comedy_2014
ohne weitere Felder zu erstellen.quelle
Firebase erlaubt keine Abfrage unter mehreren Bedingungen. Ich habe jedoch einen Weg gefunden, dies zu umgehen:
Wir müssen die anfänglich gefilterten Daten aus der Datenbank herunterladen und in einer Array-Liste speichern.
Sobald wir die anfänglich gefilterten Daten aus der Datenbank erhalten haben, müssen wir in unserem Backend weitere Filter durchführen.
quelle
Das wird funktionieren.
quelle