Firestore Queries — Filtering, Sorting, and Paginating Data with where, orderBy, and limit
In this tutorial, you will learn about Firestore Queries. We cover key concepts, practical examples, and best practices to help you master this topic.
Firestore queries use where clauses for filtering, orderBy for sorting, limit and cursor-based pagination for limiting results, supporting compound queries with Composite indexes.
What You'll Learn
- Writing where conditions for field filtering
- Sorting with orderBy and limiting results
- Cursor-based pagination for large datasets
Why It Matters
Efficient queries reduce Firestore read costs and improve application performance. Understanding query limitations prevents runtime errors. DodaTech's real-time dashboard uses optimized Firestore queries for fast data display.
flowchart LR
A["Query"] --> B{"Has where?"}
B -->|"Yes"| C["Filter by field conditions"]
B -->|"No"| D["Return all documents"]
C --> E{"Has orderBy?"}
E -->|"Yes"| F["Sort results"]
E -->|"No"| G["Default ordering"]
F --> H{"Has limit?"}
H -->|"Yes"| I["Return limited results"]
H -->|"No"| J["Return all (up to 1000)"]
Code Examples
// Basic queries with where
import { collection, query, where, getDocs } from 'firebase/firestore';
// Filter by field value
const q1 = query(
collection(db, 'users'),
where('role', '==', 'admin')
);
// Filter by multiple conditions
const q2 = query(
collection(db, 'users'),
where('role', '==', 'user'),
where('isActive', '==', true)
);
// Range filters
const q3 = query(
collection(db, 'purchases'),
where('amount', '>=', 10),
where('amount', '<=', 100)
);
const snapshot = await getDocs(q1);
snapshot.forEach(doc => {
console.log(doc.id, '=>', doc.data());
});
// Sorting and pagination
import { orderBy, limit, startAfter, query } from 'firebase/firestore';
// Sort results
const qSorted = query(
collection(db, 'users'),
orderBy('createdAt', 'desc'),
limit(10)
);
// Cursor-based pagination
async function getPage(lastDoc) {
const q = lastDoc
? query(
collection(db, 'users'),
orderBy('createdAt', 'desc'),
startAfter(lastDoc),
limit(10)
)
: query(
collection(db, 'users'),
orderBy('createdAt', 'desc'),
limit(10)
);
const snapshot = await getDocs(q);
const docs = snapshot.docs.map(d => ({ id: d.id, ...d.data() }));
const lastVisible = snapshot.docs[snapshot.docs.length - 1];
return { docs, lastVisible, hasMore: snapshot.docs.length === 10 };
}
# Python Firestore queries
from google.cloud import firestore
from google.cloud.firestore import FieldFilter
db = firestore.Client()
# Simple query
users = (
db.collection('users')
.where(filter=FieldFilter('role', '==', 'user'))
.stream()
)
# Compound query
active_admins = (
db.collection('users')
.where(filter=FieldFilter('role', '==', 'admin'))
.where(filter=FieldFilter('isActive', '==', True))
.stream()
)
# With ordering and limit
recent = (
db.collection('purchases')
.order_by('createdAt', direction=firestore.Query.DESCENDING)
.limit(20)
.stream()
)
for doc in recent:
print(f'{doc.id}: {doc.to_dict()}')
Common Mistakes
1. Using OrderBy on a Field Without a Where Equality Filter
Range filters and orderBy on different fields require a composite index.
2. Forgetting to Create Composite Indexes
Compound queries fail without a corresponding composite index.
3. Using Offset Instead of Cursors
Offset-based pagination reads all skipped documents, costing reads. Use cursors.
4. Not Limiting Results
Without limit, queries return up to 1000 documents by default.
5. Querying Across Multiple Collections
Firestore queries operate on a single collection. Use collection group queries for cross-collection needs.
Practice Questions
- What is the max documents a query returns without limit?
- How do you filter by multiple field conditions?
- What is cursor-based pagination and why use it?
- When do you need a composite index?
- Can you query across multiple collections?
Answers:
- 1000 documents.
- Use multiple where conditions in the same query, separated by commas.
- Pagination using startAfter/startAt instead of offset to avoid reading skipped documents.
- When using equality filters on different fields, or range filters with orderBy on different fields.
- Not directly. Use collection group queries for documents with the same collection name across subcollections.
Challenge: Build a paginated user list with Firestore queries. Implement filtering by role and status, sorting by creation date, cursor-based pagination with previous/next buttons, and real-time updates when new users are added.
FAQ
Mini Project
Build a Firestore query playground: a web interface that lets users select a collection, add where conditions, choose sorting, set pagination, and see the results. Show the generated query and performance metrics (time, documents read).
What's Next
Explore Firestore compound queries with multiple conditions and composite indexes, then learn about Firestore indexes for query performance.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro