Firestore Data Model — Collections, Documents, and Subcollections Design
In this tutorial, you will learn about Firestore Data Model. We cover key concepts, practical examples, and best practices to help you master this topic.
Firestore uses a NoSQL data model with collections containing documents, which can contain subcollections. Documents are JSON-like objects with key-value pairs supporting various data types.
What You'll Learn
- Firestore's document/collection hierarchy
- Choosing document IDs and structuring data
- When to use subcollections vs nested fields
Why It Matters
Firestore data model design directly impacts query performance, cost, and scalability. Poor schema design leads to slow queries and excessive read costs. DodaTech uses optimized Firestore models for its user and device management systems.
flowchart TD
A["Root"] --> B["users (collection)"]
B --> C["user123 (document)"]
B --> D["user456 (document)"]
C --> E["name: 'Alice'"]
C --> F["email: 'alice@example.com'"]
C --> G["purchases (subcollection)"]
G --> H["purchase1 (document)"]
G --> I["purchase2 (document)"]
C --> J["settings (subcollection)"]
J --> K["prefs (document)"]
Code Examples
// Creating documents in Firestore
import { collection, doc, setDoc } from 'firebase/firestore';
// Collection reference
const usersRef = collection(db, 'users');
// Add document with auto-generated ID
import { addDoc } from 'firebase/firestore';
const docRef = await addDoc(usersRef, {
name: 'Alice Johnson',
email: 'alice@example.com',
createdAt: new Date(),
role: 'user',
isActive: true
});
// Add document with custom ID
await setDoc(doc(db, 'users', 'alice@example.com'), {
name: 'Alice Johnson',
email: 'alice@example.com',
createdAt: new Date()
});
// Working with subcollections
const userDocRef = doc(db, 'users', 'alice@example.com');
// Create subcollection under user document
const purchasesRef = collection(userDocRef, 'purchases');
await addDoc(purchasesRef, {
item: 'Antivirus Pro',
price: 29.99,
purchaseDate: new Date()
});
// Data types supported
await setDoc(doc(db, 'config', 'app-settings'), {
stringField: 'hello',
numberField: 42,
booleanField: true,
nullField: null,
arrayField: [1, 2, 3],
mapField: { key: 'value' },
timestampField: new Date(),
referenceField: doc(db, 'users', 'alice@example.com'),
geoPointField: new GeoPoint(40.7128, -74.0060)
});
# Python Firestore data model
from google.cloud import firestore
db = firestore.Client()
# Create document
user_ref = db.collection('users').document('alice@example.com')
user_ref.set({
'name': 'Alice Johnson',
'email': 'alice@example.com',
'createdAt': firestore.SERVER_TIMESTAMP,
'preferences': {
'theme': 'dark',
'notifications': True
}
})
# Create subcollection
purchase_ref = user_ref.collection('purchases').document()
purchase_ref.set({
'item': 'Pro Plan',
'amount': 29.99,
'date': firestore.SERVER_TIMESTAMP
})
Common Mistakes
1. Nesting Data Too Deeply
Firestore documents have a 1 MiB size limit. Flatten data and use collections for large datasets.
2. Using Auto-Generated IDs When Meaningful IDs Are Better
When the ID is known (email, username), use setDoc with a custom ID instead of addDoc.
3. Creating Too Many Subcollections
Subcollections add complexity. Use nested maps for related data that is always fetched together.
4. Forgetting About Document Size Limits
Documents are limited to 1 MiB. Store large blobs in Storage, not Firestore.
5. Not Indexing Fields Used in Queries
Firestore requires indexes for compound queries. Create indexes before running complex queries.
Practice Questions
- What is the maximum size of a Firestore document?
- What is the difference between addDoc and setDoc?
- When should you use subcollections vs nested objects?
- How many levels of subcollections can you create?
- What data types does Firestore support?
Answers:
- 1 MiB.
- addDoc auto-generates the document ID; setDoc uses a specified ID.
- Use subcollections for growing lists (purchases, messages) and nested objects for fixed related data.
- There is no limit to subcollection depth, but deep nesting affects performance.
- String, number, boolean, null, array, map, timestamp, geopoint, and reference.
Challenge: Design a Firestore data model for a blogging platform with users, posts, comments, and likes. Include collections, subcollections, document IDs, and field schemas for each model. Justify each design decision.
FAQ
Mini Project
Design a Firestore data model for a task management application with users, projects, tasks, comments, and notifications. Implement the model with proper collections, subcollections, document IDs, and indexes. Write security rules to restrict access based on user roles.
What's Next
Learn how to query Firestore data using where, orderBy, limit, and offset clauses, then explore compound queries for complex filtering.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro