web-dev-qa-db-fra.com

Comment ajouter une sous-collection à un document dans Firebase Cloud Firestore

La documentation ne contient aucun exemple sur la manière d'ajouter une sous-collection à un document. Je sais comment ajouter un document à une collection et comment ajouter des données à un document, mais comment puis-je ajouter une collection (sous-collection) à un document?

Ne devrait-il pas y avoir une méthode comme celle-ci:

dbRef.document("example").addCollection("subCollection")
7
rgoncalv

En supposant que nous ayons une application de chat qui a une structure de base de données semblable à celle-ci:

 enter image description here

Pour écrire une subCollection dans un document, utilisez le code suivant:

DocumentReference messageRef = db
    .collection("rooms").document("roomA")
    .collection("messages").document("message1");

Si vous voulez créer une collection messages et appeler addDocument () 1000 fois coûtera cher, mais c'est comme cela que Firestore fonctionne. Vous pouvez passer à la base de données en temps réel Firebase si vous le souhaitez, là où le nombre d'écritures importe peu. Mais en ce qui concerne Types de données pris en charge dans Firestore, vous pouvez en fait utiliser un tableau car il est suppoert. Dans Base de données Firebase Realtime , vous pouvez également utiliser une variable array, mais il s'agit d'un anti-modèle. L'une des nombreuses raisons pour lesquelles Firebase recommande de ne pas utiliser de tableaux est que cela rend les règles de sécurité impossibles à écrire.

Cloud Firestore peut stocker des tableaux, il ne prend pas en charge l'interrogation des membres du tableau ni la mise à jour d'éléments uniques. Cependant, vous pouvez toujours modéliser ce type de données en exploitant les autres fonctionnalités de Cloud Firestore. Ici est la documentation où est très bien expliqué.

Vous ne pouvez pas non plus créer une sous-collection de 1 000 messages et les ajouter tous à la base de données tout en prenant en compte le même enregistrement. Cela sera considéré comme une opération d'écriture pour chaque message. Au total 1000 opérations. L'image ci-dessus ne montre pas comment récupérer des données, elle montre une structure de base de données dans laquelle vous avez quelque chose comme ça:

collection -> document -> subCollection -> document
7
Alex Mamo

Voici mon code:

firebase.firestore().collection($scope.longLanguage + 'Words').doc($scope.Word).set(wordData)
  .then(function() {
    console.log("Collection added to Firestore!");
    var promises = [];
    promises.Push(firebase.firestore().collection($scope.longLanguage + 'Words').doc($scope.Word).collection('AudioSources').doc($scope.accentDialect).set(accentDialectObject));
    promises.Push(firebase.firestore().collection($scope.longLanguage + 'Words').doc($scope.Word).collection('FunFacts').doc($scope.longLanguage).set(funFactObject));
    promises.Push(firebase.firestore().collection($scope.longLanguage + 'Words').doc($scope.Word).collection('Translations').doc($scope.translationLongLanguage).set(translationObject));
    Promise.all(promises).then(function() {
      console.log("All subcollections were added!");
    })
    .catch(function(error){
      console.log("Error adding subcollections to Firestore: " + error);
    });
  })
  .catch(function(error){
    console.log("Error adding document to Firestore: " + error);
  });

Cela crée une collection EnglishWords, qui a un document of. Le document of comporte trois sous-collections: AudioSources (enregistrements de la Parole aux accents américain et britannique), FunFacts et Translations. La sous-collection Translations a un document: Spanish. Le document Spanish a trois paires clé-valeur, vous indiquant que «de» est la traduction espagnole de «de».

La première ligne du code crée la collection EnglishWords. Nous attendons que la promesse soit résolue avec .then, puis nous créons les trois sous-groupes. Promise.all nous indique quand les trois sous-groupes sont définis.

IMHO, j'utilise des tableaux dans Firestore lorsque tout le tableau est téléchargé et téléchargé ensemble, c'est-à-dire que je n'ai pas besoin d'accéder à des éléments individuels. Par exemple, un tableau des lettres du mot 'of' serait ['o', 'f']. L'utilisateur peut demander "Comment puis-je épeler" de "? L'utilisateur ne va pas demander: "Quelle est la deuxième lettre de 'of'?" 

J'utilise des collections lorsque j'ai besoin d'accéder à des éléments individuels, des documents a.k.a. Avec l'ancienne base de données en temps réel Firebase, je devais télécharger des tableaux, puis parcourir les tableaux avec forEach pour obtenir l'élément que je voulais. C’était beaucoup de code, et avec une structure de données profonde et/ou de grands tableaux, je téléchargeais des tonnes de données dont je n’avais pas besoin, et je ralentissais l’application de mon application en exécutant des boucles forEach sur de grands tableaux. Firestore place les itérateurs dans la base de données, de sorte que je puisse demander un seul élément et m'envoie uniquement cet élément, me permettant ainsi d'économiser de la bande passante et d'accélérer le fonctionnement de mon application. Cela peut être sans importance pour une application Web, si votre ordinateur dispose d'une connexion haut débit, mais pour les applications mobiles avec des connexions de données médiocres et des appareils lents, cela est important.

Voici deux photos de mon Firestore:  enter image description here

 enter image description here

1

Voici une variante dans laquelle la sous-collection stocke les valeurs d'ID au niveau de la collection, plutôt dans un document où la sous-collection est un champ contenant des données supplémentaires. 

Ceci est utile pour connecter un mappage d'identifiant 1 à plusieurs sans avoir à explorer un document supplémentaire:

function fireAddStudentToClassroom(studentUserId, classroomId) {

    var db = firebase.firestore();
    var studentsClassroomRef =
        db.collection('student_class').doc(classroomId)
          .collection('students');

    studentsClassroomRef
        .doc(studentUserId)
        .set({})
        .then(function () {
            console.log('Document Added ');
        })
        .catch(function (error) {
            console.error('Error adding document: ', error);
        });
}

Merci à @ la réponse d'Alex

Ceci répond un peu à la question initiale ici, où il demande explicitement d'ajouter une collection à un document. Cependant, après avoir cherché une solution à ce scénario et ne trouvant aucune mention dans la documentation ou sur le SO, cet article semble être un endroit raisonnable pour partager les résultats

1
Gene Bo

trop tard pour une réponse mais voici ce qui a fonctionné pour moi,

        mFirebaseDatabaseReference?.collection("conversations")?.add(Conversation("User1"))
            ?.addOnSuccessListener { documentReference ->
                Log.d(TAG, "DocumentSnapshot written with ID: " + documentReference.id)
                mFirebaseDatabaseReference?.collection("conversations")?.document(documentReference.id)?.collection("messages")?.add(Message(edtMessage?.text.toString()))
            }?.addOnFailureListener { e ->
                Log.w(TAG, "Error adding document", e)
            }

ajoute un écouteur de succès pour l'ajout de document et utilise l'ID généré par Firebase pour un chemin d'accès . Utilisez cet ID pour le chemin d'accès complet d'une nouvelle collection à ajouter . I.E. - dbReference.collection ('votreNomCollection'). document (firebaseGeneratedID) .collection ('votreNomCollection'). add (votreDocumentPOJO/Object)

0
Mihir Patel