How to add subcollection to a document in Firebase Cloud Firestore

Viewed 87315

The documentation does not have any examples on how to add a subcollection to a document. I know how to add document to a collection and how to add data to a document, but how do I add a collection (subcollection) to a document?

Shouldn't there be some method like this:

dbRef.document("example").addCollection("subCollection")
8 Answers

Edit 13 Jan 2021:

According to the updated documentation regarding array membership, now it is possible to filter data based on array values using whereArrayContains() method. A simple example would be:

CollectionReference citiesRef = db.collection("cities");
citiesRef.whereArrayContains("regions", "west_coast");

This query returns every city document where the regions field is an array that contains west_coast. If the array has multiple instances of the value you query on, the document is included in the results only once.


Assuming we have a chat application that has a database structure that looks similar to this:

enter image description here

To write a subCollection in a document, please use the following code:

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

If you want to create messages collection and call addDocument() 1000 times will be expensive for sure, but this is how Firestore works. You can switch to Firebase Realtime Database if you want, where the number of writes doesn't matter. But regarding Supported Data Types in Firestore, in fact, you can use an array because is supported. In Firebase Realtime database you could also use an array, but this is which is an anti-pattern. One of the many reasons Firebase recommends against using arrays is that it makes the security rules impossible to write.

Cloud Firestore can store arrays, it does not support querying array members or updating single array elements. However, you can still model this kind of data by leveraging the other capabilities of the Cloud Firestore. Here is the documentation where is very well explained.

You also cannot create a subcollection with 1000 messages and add all of them to the database and at the same time to consider a single record. It will be considered one write operation for every message. In total 1000 operations. The picture above does not show how to retrieve data, it shows a database structure in which you have something like this:

collection -> document -> subCollection -> document

From the docs:

You do not need to "create" or "delete" collections. After you create the first document in a collection, the collection exists. If you delete all of the documents in a collection, it no longer exists.

too late for an answer but here is what worked for me,

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

add success listener for adding document and use firebase generated ID for a path. Use this ID for the complete path for a new collection you want to add. I.E. - dbReference.collection('yourCollectionName').document(firebaseGeneratedID).collection('yourCollectionName').add(yourDocumentPOJO/Object)

Here i faced the same issue and solve with the answere of @Thomas David Kehoe

db.collection("First collection Name").doc("Id of the document").collection("Nested collection Name").add({
                //your data
            }).then((data) => {
                console.log(data.id);
                console.log("Document has added")
            }).catch((err) => {
                console.log(err)
            })

Okay so I recently faced a similar problem given the recent update in the firebase/firestore documentation.

And here is a solution that worked for me

  const sendMessage = async () => {
    await setDoc(doc(db, COLLECTION_NAME, projectId, SUB_COLLECTION_NAME, nanoid()), {
      text:'this is a sample text',
      createdAt: serverTimestamp(),
      name: currentUser?.firstName + ' ' + currentUser?.lastName,
      photoUrl: currentUser?.photoUrl,
      userId: currentUser?.id,
    });
  }

You can find a similar example in the docs https://firebase.google.com/docs/firestore/data-model#web-version-9_3

chat room

If you wish to listen for live update you can use a similar method as follows

const messagesRef = collection(db, COLLECTION_NAME, projectId, SUB_COLLECTION_NAME)
      
const liveUpdate = async () => {
        const queryObj = query(messagesRef, orderBy("createdAt"), limit(25));
        onSnapshot(queryObj, (querySnapshot) => {
          const msgArr: any = [];
          querySnapshot.forEach((doc) => {
            msgArr.push({ id: doc.id, ...doc.data() })
          });
          console.log(msgArr);
        });
      }

There is no separate method to add sub-collection into the document. You can just call the collection method itself. If the collection exists it will reference that otherwise create a new one.

dbRef.document("example").collection("subCollection")
Related