26

Is there a way to check if a sub collection exists in firestore for nodejs?

Currently I am using doc.exists for documents but I need to check if a subcolletion exists within a document in order to write some data or not.

Ahsath
  • 423
  • 1
  • 7
  • 19
  • Another answer I found that works great for this is here https://stackoverflow.com/questions/46880323/how-to-check-if-a-cloud-firestore-document-exists-when-using-realtime-updates. This also works on subcollections as described here https://github.com/EddyVerbruggen/nativescript-plugin-firebase/issues/559 – Daniel Watrous Jan 07 '18 at 14:28

6 Answers6

38

Mateus' Answer didn't help me. Probably it has been changed over the time.

.collection(..).get() returns a QuerySnapshot which has the property size, so I just did:

admin.firestore
     .collection('users')
     .doc('uid')
     .collection('sub-collection')
     .limit(1)
     .get()
     .then(query => query.size);
Marcello B.
  • 4,177
  • 11
  • 45
  • 65
Eliya Cohen
  • 10,716
  • 13
  • 59
  • 116
  • Is it necessary to use .limit(1)? – Edison Pebojot Jun 10 '21 at 10:00
  • @EdisonPebojot No it is not, but this limits the query size if you don't need to fetch all the docs later on - probably good for pagination. So you could use it like this: const snapshot = await admin.firestore.collection(`users/${uid}/sub-collection`).get() const doesDocsExist = snapshot.size ? true : false – Jonas Tamoševičius Aug 05 '21 at 13:39
  • 2
    It is. It'll be faster and it will count less against your quota – Eliya Cohen Aug 05 '21 at 19:28
37

Yes, there is. You can use docs.length to know if the subcollection exists.

I made a sample to guide you, hope it helps.

 this.db.collection('users').doc('uid')
  .get().limit(1).then(
  doc => {
    if (doc.exists) {
      this.db.collection('users').doc('uid').collection('friendsSubcollection').get().
        then(sub => {
          if (sub.docs.length > 0) {
            console.log('subcollection exists');
          }
        });
    }
  });
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
5

To be more precise:

const querySnapshot = await admin.firestore().collection('users').doc('uid').collection('sub-collection').limit(1).get()
if (querySnapshot.empty) {console.log('sub-collection not existed')}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Choppy
  • 372
  • 1
  • 3
  • 9
2

This is how I was able to check if a collection exists?

I target the document path first, then if it exists, It means the collection afterwards exists and I can access it.

>  db.collection("collection_name").document("doc_name").get()
>        .addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
>                     @Override
>                     public void onComplete(@NonNull Task<DocumentSnapshot> task) {
>                         if(task.isSuccessful()){
>                             DocumentSnapshot result = task.getResult();
>                             if(result.exists()){
>                                *//this means the document exist first, hence the 
>                                 //collection afterwards the doc_name will 
>                                 //exist...now I can access the collection*  
> db.collection("collection_name").document("doc_name").collection("collection_name2").get()
> .addOnCompleteListener(task1 -> {    if(task1.isSuccessful()){
>       ...
>     } }); } } });
Sterlingking
  • 190
  • 1
  • 6
1

isEmpty property of QuerySnapshot returns true if there are no documents in the QuerySnapshot.

Thus you can simply check if isEmpty is true or false.

const subcolRef = collection(db, "parentCollectionTitle", "parentDocId", "subcollectionTitle")
const subcolSnapshot = await getDocs(subcollectionRef)

if (!subcolSnapshot.empty) {
    console.log("subcol does exists!");
} else {
    console.log("subcol does NOT exist!");
}

(Firebase v9)

Leonard
  • 2,978
  • 6
  • 21
  • 42
0

This is NextJS (React) code for checking if a sub-collection "history" exists or not in collection "users" > doc>user-Id, if it exists then take data in history, else keep have-history == false. you can then use {havehistory?<></>:<></>} for showing different info, as per data.

    const [history, setHistory] = useState([])
const [havehistory, setHavehistory] = useState(false)

if(user){
  onSnapshot(query(collection(db, "users", user.uid,"history")), (querySnapshot) => {
    if(querySnapshot){
      const historyBro = querySnapshot.docs.map((doc) => {
        return { ...doc.data(), id: doc.id };
      });
      setHistory(historyBro)
      setHavehistory(true)
    }
  })
}

make sure your imported the required modules. e.g.

import { useState } from "react";

import {db} from '../firebase'

import { collection,doc, query, onSnapshot} from "firebase/firestore";

import Link from "next/link";