Firebase の Query APIを使用して、これを試してみたくなるかもしれません:
// !!! 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());
});
しかし、Firebase の @RobDiMarco がコメントで述べているように:
複数のorderBy()
呼び出しはエラーをスローします
したがって、上記のコードは機能しません。
私はうまくいく3つのアプローチを知っています。
1. ほとんどをサーバーでフィルタリングし、残りはクライアントで行います
できることは、サーバーで 1 つを実行orderBy().startAt()./endAt()
し、残りのデータを取得して、クライアントの JavaScript コードでフィルタリングすることです。
ref
.orderBy('genre')
.equalTo('comedy')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
if (movie.lead == 'Jack Nicholson') {
console.log(movie);
}
});
2. フィルタリングする値を組み合わせたプロパティを追加します
それが十分でない場合は、ユースケースを許可するようにデータを変更/拡張することを検討する必要があります。例: ジャンル + リードを、このフィルターに使用する 1 つのプロパティに詰め込むことができます。
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_lead": "comedy_Jack Nicholson"
}, //...
基本的に、独自の複数列インデックスをそのように構築しており、次の方法でクエリを実行できます。
ref
.orderBy('genre_lead')
.equalTo('comedy_Jack Nicholson')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
David East は、そのようなプロパティの生成を支援する QueryBase というライブラリを作成しました。
相対/範囲クエリを実行することもできます。たとえば、映画をカテゴリと年でクエリできるようにしたいとします。次のデータ構造を使用します。
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson",
"genre_year": "comedy_1997"
}, //...
次に、90 年代のコメディーを次のようにクエリします。
ref
.orderBy('genre_year')
.startAt('comedy_1990')
.endAt('comedy_2000')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
console.log(movie);
});
年以外でフィルタリングする必要がある場合は、他の日付部分を降順で追加して"comedy_1997-12-25"
ください。このようにして、Firebase が文字列値に対して行う辞書式の順序は、時系列の順序と同じになります。
プロパティ内の値のこの組み合わせは、3 つ以上の値で機能しますが、複合プロパティ内の最後の値に対してのみ範囲フィルターを実行できます。
これの非常に特殊なバリアントがFirebase の GeoFire ライブラリによって実装されています。このライブラリは、場所の緯度と経度をいわゆるGeohashに結合します。これを使用して、Firebase でリアルタイムの範囲クエリを実行できます。
3. プログラムでカスタム インデックスを作成する
さらに別の方法は、この新しいクエリ API が追加される前に行ったことを実行することです: 別のノードにインデックスを作成します。
"movies"
// the same structure you have today
"by_genre"
"comedy"
"by_lead"
"Jack Nicholson"
"movie1"
"Jim Carrey"
"movie3"
"Horror"
"by_lead"
"Jack Nicholson"
"movie2"
おそらくもっと多くのアプローチがあります。たとえば、この回答は別のツリー型のカスタム インデックスを強調しています: https://stackoverflow.com/a/34105063
これらのオプションのどれもうまくいかなくても、データを Firebase に保存したい場合は、Cloud Firestore データベースの使用を検討することもできます。
Cloud Firestore は、1 つのクエリで複数の等価フィルタを処理できますが、範囲フィルタは 1 つだけです。内部的には基本的に同じクエリ モデルを使用しますが、複合プロパティを自動生成するように見えます。複合クエリに関する Firestore のドキュメントを参照してください。