{
"movies": {
"movie1": {
"genre": "comedy",
"name": "As good as it gets",
"lead": "Jack Nicholson"
},
"movie2": {
"genre": "Horror",
"name": "The Shining",
"lead": "Jack Nicholson"
},
"movie3": {
"genre": "comedy",
"name": "The Mask",
"lead": "Jim Carrey"
}
}
}
私は Firebase 初心者です。 AND上のデータから結果を取得するにはどうすればよいですかgenre = 'comedy'
lead = 'Jack Nicholson'
?
どのような選択肢がありますか?
ベストアンサー1
使用Firebase のクエリ 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. サーバー上で大部分のフィルタリングを行い、残りはクライアント上で行う
できることは、orderBy().startAt()./endAt()
サーバー上で1 つ実行し、残りのデータを取得して、クライアント上の JavaScript コードでフィルター処理することです。
ref
.orderBy('genre')
.equalTo('comedy')
.on('child_added', function(snapshot) {
var movie = snapshot.val();
if (movie.lead == 'Jack Nicholson') {
console.log(movie);
}
});
2. フィルタリングする値を組み合わせたプロパティを追加します
それでも十分でない場合は、ユースケースに合わせてデータを変更/拡張することを検討する必要があります。たとえば、このフィルターに使用する単一のプロパティに、ジャンル + リードを入れることができます。
"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);
});
デイビッド・イーストはこのようなプロパティを生成するのに役立つ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 が文字列値に対して行う辞書式順序は、時系列順序と同じになります。
プロパティ内の値の結合は 2 つ以上の値で機能しますが、範囲フィルターは複合プロパティの最後の値に対してのみ実行できます。
この非常に特殊なバリエーションは、Firebase 用 GeoFire ライブラリこのライブラリは、場所の緯度と経度をいわゆるジオハッシュこれを使用して、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にデータを保存したい場合は、Firebaseの使用も検討してください。Cloud Firestore データベース。
Cloud Firestoreは、1つのクエリで複数の等式フィルタを処理できますが、範囲フィルタは1つしか処理できません。内部的には基本的に同じクエリモデルを使用していますが、複合プロパティを自動生成するようなものです。Firestoreのドキュメントを参照してください。複合クエリ。