web-dev-qa-db-ja.com

Firestoreクエリアコレクション

私はあなたが新しいFirebase Firestoreでサブコレクションを問い合わせることができると読んだと思いました、しかし、私は例を見ません。たとえば、次のようにFirestoreを設定します。

  • ダンス[コレクション]
    • danceName
    • 歌[コレクション]
      • 曲名

「songName == 'X'の場合はすべてのダンスを検索する」というクエリを実行する方法を教えてください。

86
Nelson.b.austin

更新2019-05-07

今日私達は コレクショングループクエリ をリリースしました、そしてこれらはあなたがサブコレクションを越えてクエリすることを可能にします。

たとえば、Web SDKでは次のようになります。

db.collectionGroup('Songs')
  .where('songName', '==', 'X')
  .get()

これは、コレクションパスの最後の部分が 'Songs'であるコレクション内のドキュメントと一致します。

あなたの最初の質問は、songName == 'X'のところで踊りを見つけることでしたが、それでも直接不可能なのです。

元の答え

これはまだ存在しない機能です。これは「コレクショングループクエリ」と呼ばれ、どのダンスに含まれているかに関係なく、すべての曲をクエリできます。これは私たちがサポートしようとしているものですが、それがいつ来るかについての具体的なタイムラインを持っていません。

この時点での代替構造は、曲をトップレベルのコレクションにし、その曲をどのダンスにするかをその曲の特性の一部にすることです。

99
Gil Gilbert

UPDATEFirestoreはarray-containsをサポートするようになりました

これらの文書を持っている

    {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);

これが役に立つことを願っています。

18
norgematos

曲をコレクションとしてではなくオブジェクトとして保存するとどうなりますか?それぞれの踊りは、フィールドとしての歌とともに、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);
    });
13
dmartins

UPDATE 2019

FirestoreはCollection Group Queriesをリリースしました。上記のGilの回答または公式の Collection Group Query Documentation を参照してください。


前回の回答

Gil Gilbertによって述べられたように、それはあたかもコレクショングループクエリが現在進行中であるかのように思われます。当面の間は、ルートレベルのコレクションを使用し、それらのコレクション間を文書UIDを使用してリンクするだけの方がおそらく良いでしょう。

まだ知らない人のために、Jeff Delaneyは AngularFirebase でFirebase(およびAngular)を使っている人のための素晴らしいガイドとリソースを用意しています。

Firestore NoSQLリレーショナルデータモデリング - ここで彼はNoSQLとFirestore DBの構造化の基本を打ち破ります。

例によるFirestoreを使用した高度なデータモデリング - これらは、頭の中で気を配るためのより高度な手法です。 Firestoreのスキルを次のレベルに引き上げたいという方に最適の読書

8
Matthew Mullin

クエリ制限

Cloud Firestoreは、次の種類のクエリをサポートしません。

  1. さまざまなフィールドに範囲フィルターを使用した照会。

  2. 複数のコレクションまたはサブコレクションにわたる単一のクエリ。各クエリは、ドキュメントの単一のコレクションに対して実行されます。データ構造がクエリに与える影響の詳細については、 データ構造を選択する を参照してください。

  3. 論理ORクエリ。この場合、OR条件ごとに個別のクエリを作成し、そのクエリ結果をアプリにマージする必要があります。
  4. !=句を使用したクエリこの場合、クエリを大なりクエリと小なりクエリに分割する必要があります。たとえば、query句where( "age"、 "!="、 "30")はサポートされていませんが、2つのクエリを組み合わせて同じ結果セットを取得できます。1つはwhere where( "age"、 "< "、" 30 ")と句があるもの(" age "、"> "、30)。
1
ggDeGreat
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);
        });
1
Alok Prusty

2019年7月8日の新しい更新:

db.collectionGroup('Songs')
  .where('songName', isEqualTo:'X')
  .get()
1
Nhật Trần

フラットデータ構造を使用することをお勧めします。
このページでは、ドキュメントは異なるデータ構造の長所と短所 を指定します

特にサブコレクションを持つ構造の制限について

サブコレクションを簡単に削除したり、サブコレクション間で複合クエリを実行したりすることはできません。

フラットデータ構造の主張されている利点と対照的に。

ルートレベルのコレクションは、各コレクション内での強力なクエリと共に、最も高い柔軟性とスケーラビリティを提供します。

1
MattClimbs

あなたはいつでもこのように検索することができます: -

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;
      }
    })
);
0
Ankur Biswas