web-dev-qa-db-fra.com

Firestore récupère tous les documents et sous-collections de la collection racine

Dis que j'ai ce genre de structure

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

A et B sont collections tandis que a et b sont documents.
Existe-t-il un moyen de récupérer tout le contenu d’un document racine en une seule requête?
Si j'interroge comme ça

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

Je viens d'obtenir le champ name:'Tim'. Ce que je veux, c'est aussi obtenir tous les documents de B.
Je souhaite que ma requête revienne

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

Est-il possible ou dois-je vraiment faire plusieurs requêtes une pour chaque collection: /?

Supposons que j'ai un arbre de collections imbriqué très profond représentant le profil utilisateur, mes coûts vont augmenter énormément, car chaque fois que je charge un profil utilisateur, j'ai un multiplicateur de demandes de lecture 1 x N où N est la profondeur de mon arbre: /.

35
r4id4

Comme nous le savons, les requêtes dans Cloud Firestore sont peu profondes par défaut. Ce type de requête n'est pas pris en charge, bien que Google puisse en tenir compte à l'avenir.

20
J Prakash

Si les coûts de chaque extraction vous préoccupent, vous devrez structurer vos données en fonction de vos besoins en vue/en attraction, plutôt que de ce que vous préférez pour une structure parfaite. Si vous devez rassembler ces éléments à chaque fois, pensez à utiliser "cartes" pour les éléments qui ne nécessitent pas réellement de sous-collections de documents.

Dans cet exemple, "préférences" est une carte.

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

La taille de chaque document est également limitée à 1 Mo. Par conséquent, si vous devez stocker quelque chose pour cet utilisateur qui évoluera et continuera de croître, comme les enregistrements de journaux, il serait alors logique de décomposer les journaux en une sous-collection qui ne sera extraite que lorsque vous le souhaitez, en transformant chaque entrée de journal en un document distinct ... Et si tous les journaux de tous les utilisateurs sont stockés dans une collection parent distincte ou si une sous-collection de chaque utilisateur dépend réellement de la manière dont vous allez extraire les journaux et de ce qui va en résulter à des vitesses rapides, contrebalancées par le coût des tractions. Si vous montrez à cet utilisateur ses 10 dernières recherches, un journal de recherche serait logique en tant que sous-collection. Si vous extrayez toutes les données de recherche pour tous les utilisateurs à des fins d'analyse, une collecte de niveau parent distinct serait utile, car vous pouvez extraire tous les journaux en un seul flux, afin d'éviter d'avoir à extraire les journaux de chaque utilisateur séparément.

Vous pouvez également imbriquer vos tractions et vos promesses à des fins de commodité.

  // 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

En ajoutant à Matt R answer, si vous utilisez babel ou que vous pouvez utiliser async/wait, vous pouvez obtenir le même résultat avec moins de code (no 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