web-dev-qa-db-ja.com

Firebase Cloud Firestoreのドキュメントにサブコレクションを追加する方法

ドキュメントには、サブコレクションをドキュメントに追加する方法の例はありません。ドキュメントをコレクションに追加する方法とデータをドキュメントに追加する方法は知っていますが、コレクション(サブコレクション)をドキュメントに追加するにはどうすればよいですか?

次のような方法はないはずです。

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

次のようなデータベース構造を持つチャットアプリケーションがあるとします。

enter image description here

ドキュメントにsubCollectionを書き込むには、次のコードを使用してください。

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

messagesコレクションを作成してaddDocument()を1000回呼び出す場合は確かにコストがかかりますが、これがFirestoreの仕組みです。必要に応じて、Firebase Realtime Databaseに切り替えることができます。書き込みの数は重要ではありません。しかし、Firestoreの サポートされるデータ型 に関しては、実際にはサポートされているため配列を使用できます。 Firebase Realtime database では、arrayも使用できますが、これはアンチパターンです。 Firebaseが配列の使用を推奨しない多くの理由の1つは、セキュリティルールを記述できないことです。

Cloud Firestoreは配列を保存できますが、配列メンバーのクエリや単一の配列要素の更新はサポートしていません。ただし、Cloud Firestoreの他の機能を活用することで、この種のデータを引き続きモデル化できます。 ここ は、非常に適切に説明されているドキュメントです。

また、1000個のメッセージを含むサブコレクションを作成し、それらすべてをデータベースに追加すると同時に、単一のレコードを考慮することもできません。すべてのメッセージに対して1つの書き込み操作と見なされます。合計1000回の操作。上の図は、データの取得方法を示しているのではなく、次のようなデータベース構造を示しています。

collection -> document -> subCollection -> document
15
Alex Mamo

私のコードは次のとおりです。

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

これにより、ドキュメントEnglishWordsを持つコレクションofが作成されます。ドキュメントofには、AudioSources(アメリカとイギリスのアクセントでの単語の記録)、FunFacts、およびTranslationsの3つのサブコレクションがあります。サブコレクションTranslationsには、Spanishという1つのドキュメントがあります。 Spanishドキュメントには3つのキーと値のペアがあり、「de」はスペイン語の「of」の翻訳であることがわかります。

コードの最初の行は、コレクションEnglishWordsを作成します。 .thenで解決する約束を待ってから、3つのサブコレクションを作成します。 Promise.allは、3つのサブコレクションがすべて設定されたことを示します。

私見、アレイ全体が一緒にアップロードおよびダウンロードされる場合、Firestoreでアレイを使用します。つまり、個々の要素にアクセスする必要はありません。たとえば、「of」という単語の文字の配列は['o', 'f']になります。ユーザーは、「 'of'のつづりをどうすればよいですか」と尋ねることができます。ユーザーは、「 'of'の2番目の文字は何ですか?」とは尋ねません。

個々の要素、つまりドキュメントにアクセスする必要がある場合、コレクションを使用します。古いFirebase Realtime Databaseでは、配列をダウンロードし、forEachを使用して配列を反復処理して、必要な要素を取得する必要がありました。これは大量のコードであり、深いデータ構造や大きな配列を使用すると、必要のない大量のデータをダウンロードし、大きな配列でforEachループの実行を遅くしていました。 Firestoreはデータベースにイテレータを配置します。そのため、単一の要素をリクエストし、その要素のみを送信して、帯域幅を節約し、アプリの実行を高速化します。これは、コンピューターにブロードバンド接続がある場合、Webアプリでは問題になりませんが、データ接続が遅く、デバイスが遅いモバイルアプリでは重要です。

Firestoreの2つの写真を次に示します。 enter image description here

enter image description here

2

これは、サブコレクションが追加データを含むフィールドであるドキュメント内ではなく、サブコレクションがコレクションレベルでID値を格納するバリエーションです。

これは、1対多IDマッピングを接続するのに役立ちます。追加のドキュメント:

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

@ Alex's answer に感謝

これは、コレクションをドキュメントに追加するように明示的に要求するここでの元の質問とは少し異なります。ただし、このシナリオの解決策を検索し、ドキュメントまたはSOで言及が見つからない場合、この投稿は調査結果を共有するのに妥当な場所のようです

1
Gene Bo

答えには遅すぎますが、ここに私のために働いたものがあります、

        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)
            }

ドキュメントを追加するための成功リスナーを追加し、パスにfirebaseが生成したIDを使用します。追加する新しいコレクションの完全なパスにこのIDを使用します。 I.E. -dbReference.collection( 'yourCollectionName')。document(firebaseGeneratedID).collection( 'yourCollectionName')。add(yourDocumentPOJO/Object)

0
Mihir Patel