新しいFirebase Firestoreでサブコレクションをクエリできると読んだと思いましたが、例がありません。たとえば、Firestoreは次のように設定されています。
- ダンス[コレクション]
- danceName
- 曲[コレクション]
- 曲名
「songName == 'X'であるすべてのダンスを検索する」をクエリするにはどうすればよいですか
新しいFirebase Firestoreでサブコレクションをクエリできると読んだと思いましたが、例がありません。たとえば、Firestoreは次のように設定されています。
「songName == 'X'であるすべてのダンスを検索する」をクエリするにはどうすればよいですか
回答:
アップデート2019-05-07
本日、コレクショングループクエリをリリースしました。これにより、サブコレクション全体でクエリを実行できます。
したがって、たとえばWeb SDKでは次のようになります。
db.collectionGroup('Songs')
.where('songName', '==', 'X')
.get()
これは、コレクションパスの最後の部分が「曲」であるすべてのコレクションのドキュメントに一致します。
あなたの元の質問は、songName == 'X'であるダンスを見つけることでしたが、これはまだ直接不可能ですが、一致する各ソングについて、親をロードできます。
元の答え
これはまだ存在しない機能です。これは「コレクショングループクエリ」と呼ばれ、どのダンスに含まれているかに関係なく、すべての曲をクエリできます。これは私たちがサポートするつもりですが、いつ来るかについての具体的なタイムラインはありません。
この時点での代替構造は、曲をトップレベルのコレクションにして、どのダンスが曲の一部であるかを曲のプロパティの一部にすることです。
UPDATE Now Firestoreは配列コンテナをサポートします
これらの文書を持っている
{danceName: 'Danca name 1', songName: ['Title1','Title2']}
{danceName: 'Danca name 2', songName: ['Title3']}
このようにしてください
collection("Dances")
.where("songName", "array-contains", "Title1")
.get()...
@ Nelson.b.austin firestoreにはまだないので、フラットな構造にすることをお勧めします。
Dances = {
danceName: 'Dance name 1',
songName_Title1: true,
songName_Title2: true,
songName_Title3: false
}
そのようにして、あなたはそれを成し遂げることができます:
var songTitle = 'Title1';
var dances = db.collection("Dances");
var query = dances.where("songName_"+songTitle, "==", true);
これがお役に立てば幸いです。
songName_Title3: false
役立ちますか?私が間違っていない場合は、特定の曲名のないダンスを検索するためにのみ使用できます。そのような結果songName_Title3: false
をdances.where("songName_"+songTitle, "==", false);
返す必要があると仮定すると、すべてのダンスがすべての可能な曲にブールフラグを持つことは意味がありません。名前...
曲をコレクションではなくオブジェクトとして保存するとどうなりますか?各ダンスのように、歌をフィールドとして:タイプObject(コレクションではない)
{
danceName: "My Dance",
songs: {
"aNameOfASong": true,
"aNameOfAnotherSong": true,
}
}
次に、aNameOfASongを使用してすべてのダンスを照会できます。
db.collection('Dances')
.where('songs.aNameOfASong', '==', true)
.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
console.log(doc.id, " => ", doc.data());
});
})
.catch(function(error) {
console.log("Error getting documents: ", error);
});
アップデート2019
Firestoreはコレクショングループクエリをリリースしました。上記のギルの回答または公式のコレクショングループクエリドキュメントを参照してください
前の回答
ギル・ギルバートが述べたように、コレクション・グループのクエリが現在作業中のようです。それまでの間は、ルートレベルのコレクションを使用して、ドキュメントUIDを使用してこれらのコレクションをリンクすることをお勧めします。
まだ知らない人のために、Jeff Delaneyは、AngularFirebaseでFirebase(およびAngular)を操作する人のための素晴らしいガイドとリソースをいくつか用意しています。
Firestore NoSQL Relational Data Modeling-ここでは、NoSQLとFirestore DBの構造化の基本を分析しています
例によるFirestoreを使用した高度なデータモデリング -これらは、心に留めておくためのより高度な手法です。Firestoreのスキルを次のレベルに引き上げたい方におすすめの読み物
あなたはいつもこのように検索できます:-
this.key$ = new BehaviorSubject(null);
return this.key$.switchMap(key =>
this.angFirestore
.collection("dances").doc("danceName").collections("songs", ref =>
ref
.where("songName", "==", X)
)
.snapshotChanges()
.map(actions => {
if (actions.toString()) {
return actions.map(a => {
const data = a.payload.doc.data() as Dance;
const id = a.payload.doc.id;
return { id, ...data };
});
} else {
return false;
}
})
);
クエリの制限
Cloud Firestoreは、次のタイプのクエリをサポートしていません。
さまざまなフィールドで範囲フィルターを使用したクエリ。
複数のコレクションまたはサブコレクションにわたる単一のクエリ。各クエリは、ドキュメントの単一のコレクションに対して実行されます。データ構造がクエリに与える影響の詳細については、「データ構造を選択する」を参照してください 。
論理ORクエリ。この場合、OR条件ごとに個別のクエリを作成し、クエリ結果をアプリにマージする必要があります。
!=句を使用したクエリ。この場合、クエリを大なりクエリと小なりクエリに分割する必要があります。たとえば、クエリ句where( "age"、 "!="、 "30")はサポートされていませんが、where( "age"、 "< "、" 30 ")およびwhere(" age "、"> "、30)の句を含むもの。
var songs = []
db.collection('Dances')
.where('songs.aNameOfASong', '==', true)
.get()
.then(function(querySnapshot) {
var songLength = querySnapshot.size
var i=0;
querySnapshot.forEach(function(doc) {
songs.push(doc.data())
i ++;
if(songLength===i){
console.log(songs
}
console.log(doc.id, " => ", doc.data());
});
})
.catch(function(error) {
console.log("Error getting documents: ", error);
});
解決策を見つけました。こちらをご確認ください。
var museums = Firestore.instance.collectionGroup('Songs').where('songName', isEqualTo: "X");
museums.getDocuments().then((querySnapshot) {
setState(() {
songCounts= querySnapshot.documents.length.toString();
});
});
そして、あなたはconsole.firebase.google.comからクラウドファイアストアのデータ、ルール、インデックス、使用法タブを見ることができます。最後に、[インデックス]タブでインデックスを設定する必要があります。
ここにコレクションIDといくつかのフィールド値を入力します。次に、コレクショングループオプションを選択します。楽しめ。ありがとう
ここではObservablesとAngularFireラッパーを使用していますが、ここでどうやってそれを実現できたかを示します。
それはちょっとおかしいです、私はまだ観測可能物について学んでいて、多分それをやり過ぎました。しかし、それは素晴らしい練習でした。
いくつかの説明(RxJSの専門家ではありません):
in
クエリの最大角度がかかります)。type Song = {id: string, name: string};
type Dance = {id: string, name: string, songs: Song[]};
const songId$: Observable<Song> = new Observable();
const dance$ = songId$.pipe(
take(1), // Only take 1 song name
switchMap( v =>
// Query across collectionGroup to get all instances.
this.db.collectionGroup('songs', ref =>
ref.where('id', '==', v.id)).get()
),
switchMap( v => {
// map the Song to the parent Dance, return the Dance ids
const obs: string[] = [];
v.docs.forEach(docRef => {
// We invoke parent twice to go from doc->collection->doc
obs.push(docRef.ref.parent.parent.id);
});
// Because we return an array here this one emit becomes N
return obs;
}),
// Firebase IN support up to 10 values so we partition the data to query the Dances
bufferCount(10),
mergeMap( v => { // query every partition in parallel
return this.db.collection('dances', ref => {
return ref.where( firebase.firestore.FieldPath.documentId(), 'in', v);
}).get();
}),
switchMap( v => {
// Almost there now just need to extract the data from the QuerySnapshots
const obs: Dance[] = [];
v.docs.forEach(docRef => {
obs.push({
...docRef.data(),
id: docRef.id
} as Dance);
});
return of(obs);
}),
// And finally we reduce the docs fetched into a single array.
reduce((acc, value) => acc.concat(value), []),
);
const parentDances = await dance$.toPromise();
コードをコピーして貼り付け、変数名をあなたの名前に変更しました。エラーがあるかどうかはわかりませんが、問題なく動作しました。エラーを見つけた場合、またはいくつかの模擬暖炉でテストするためのより良い方法を提案できる場合は、お知らせください。