Firestore Subcollections

August 8, 2019

Should I use Subcollections?

TLDR: 80% of the time my answer is No.

  • Watch these videos for see pros and cons (and example) of subcollections: Cloud Firestore Data Modeling (Google I/O’19) and How to Structure Your Data | Get to Know Cloud Firestore #5.
  • Firestore used to have the limitation that you could not query across subcollections, but that is solved with Collection Group Queries (though it does involved more indexes).
  • If you want the most flexibility in terms of query (or simplicity in data model design), don’t use subcollections.
  • If you are 95% sure you will not perform query across sub-collections most of the time (assuming reviews is subcollection of restaurant, where mostly you show reviews when user click on a restaurant, and you most probably won’t show all reviews written by a user).
  • One advantage of subcollections is saving some index keys (in the case of reviews is subcollection of restaurant, you don’t need to store restaurant_id as index key in reviews). Without subcollections you might utilize composite index keys more for query.
  • Subcollections also allow inheritance of security rules (might or might not be useful).
  • Personal Opinion: Subcollections might looks nice in terms of data structure design, but you must know its caveats which might not be that obvious without some experiences.

PS: I used very little subcollections so far.

Subcollections

Documents in subcollections can contain subcollections as well, allowing you to further nest data. You can nest data up to 100 levels deep.

Deleting a document does not delete its subcollections! Refer Delete collections.

DocumentReference

val db = ...

parentDocRef = db.collection("restaurant").document("cafe-abc")
reviewDocRef = parentDocRef.collection("review").document()

Security Rules

service cloud.firestore {
  match /databases/{database}/documents {
    match /restaurant/{restaurant_id} {
      allow read, write: if <condition>;

        match /reviews/{review_id} {
          allow read, write: if <condition>;
        }
    }
  }
}
This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.