web-dev-qa-db-ja.com

Firestoreは、ルートコレクションのすべてのドキュメントとサブコレクションを取得します

このような構造があるとしましょう

    A (collection): { 
       a (doc): {
           name:'Tim',
           B (collection):{
               b (doc): {
                      color:'blue'
               }
             }
          }
    }

ここで、ABコレクションですが、abドキュメントです。
ルートドキュメントに含まれるすべてのものを1つのクエリで取得する方法はありますか?
このようにクエリした場合

db.collection("A").doc("a").get()

name:'Tim'フィールドを取得します。私が欲しいのは、すべてのBのドキュメントも取得することです。
基本的にクエリが返されることを望みます

         {
           user:'Tim',
           B (collection):{
               b (doc): {
                      color:'blue'
               }
             }
          }

それは可能ですか、それとも本当にコレクションごとに複数のクエリを作成する必要がありますか:/?

ユーザープロファイルを表すコレクションの非常に深いネストツリーがあるとします。ユーザープロファイルを読み込むたびに、読み取り要求の乗数1 x Nがあります(Nはツリーの深さ) /。

35
r4id4

知っているように、Cloud Firestoreでのクエリはデフォルトで浅いです。このタイプのクエリはサポートされていませんが、今後Googleで検討される可能性があります。

20
J Prakash

各プルのコストが心配な場合は、完全な構造に望ましいものではなく、一般的なビュー/プルのニーズに従ってデータを構造化する必要があります。毎回これらのものをまとめる必要がある場合は、 「マップ」を使用することを考慮してください 実際にドキュメントのサブコレクションである必要のないものについて。

この例では、「preferences」はマップです。

{
  user: "Tim",
  preferences: {
      color: "blue",
      nickname: "Timster"
  }
}

各ドキュメントのサイズも1MBに制限されているため、このユーザー向けに、ログレコードのように拡大および拡大し続けるものを保存する必要がある場合は、ログをサブコレクションに分割して、各ログエントリを個別のドキュメントにする...そして、すべてのユーザーのすべてのログを個別の親コレクションに保存するか、各ユーザーのサブコレクションを保存するかは、ログの取得方法と結果に依存します。高速で、プルのコストとバランスが取れています。このユーザーに最後の10回の検索を表示する場合、検索ログはサブコレクションとして意味があります。分析のためにすべてのユーザーのすべての検索データをプルする場合、すべてのログを1つのプルでプルできるため、各ユーザーから個別にログをプルする必要がないため、個別の親レベルのコレクションが意味を持ちます。

また、便宜上、プルとプロミスをネストすることもできます。

  // Get reference to all of the documents
  console.log("Retrieving list of documents in collection");
  let documents = collectionRef.limit(1).get()
    .then(snapshot => {
      snapshot.forEach(doc => {
        console.log("Parent Document ID: ", doc.id);

        let subCollectionDocs = collectionRef.doc(doc.id).collection("subCollection").get()
          .then(snapshot => {
            snapshot.forEach(doc => {
              console.log("Sub Document ID: ", doc.id);
            })
          }).catch(err => {
            console.log("Error getting sub-collection documents", err);
          })
      });
    }).catch(err => {
    console.log("Error getting documents", err);
  });
24
Matthew Rideout

Matt Rの回答に加えて、babelを使用している場合、またはasync/awaitを使用できる場合、少ないコードで同じ結果を得ることができます(catch/then):

// Get reference to all of the documents
console.log("Retrieving list of documents in collection");
let documents = await collectionRef.get();

documents.forEach(async doc => {
  console.log("Parent Document ID: ", doc.id);
  let subCollectionDocs = await collectionRef.doc(doc.id).collection("subCollection").get()
  subCollectionDocs.forEach(subCollectionDoc => {
    subCollectionDoc.forEach(doc => {
      console.log("Sub Document ID: ", doc.id);
    })
});
4
Or Duan