
Cloud
Learning Level
Advanced Firestore queries enable you to retrieve exactly the data you need with filtering, ordering, pagination, and real-time synchronization.
By the end of this lesson, you'll understand:
import { collection, query, where, orderBy, limit, getDocs } from "firebase/firestore";
import { db } from "./firebase-config";
// Simple query
const q = query(
collection(db, "posts"),
where("published", "==", true),
orderBy("createdAt", "desc"),
limit(10)
);
const snapshot = await getDocs(q);
snapshot.forEach(doc => {
console.log(doc.id, doc.data());
});import { query, where, collection, getDocs } from "firebase/firestore";
// Multiple conditions (AND)
const q = query(
collection(db, "posts"),
where("author", "==", "userId123"),
where("published", "==", true),
where("category", "==", "tech"),
orderBy("createdAt", "desc")
);
const results = await getDocs(q);import { query, where, collection, getDocs } from "firebase/firestore";
// Range queries
const q = query(
collection(db, "products"),
where("price", ">=", 10),
where("price", "<=", 100),
where("inStock", "==", true)
);
const results = await getDocs(q);import { query, orderBy, limit, startAfter, collection, getDocs } from "firebase/firestore";
let lastVisible;
// First page
const firstPageQuery = query(
collection(db, "posts"),
orderBy("createdAt", "desc"),
limit(10)
);
const firstSnapshot = await getDocs(firstPageQuery);
lastVisible = firstSnapshot.docs[firstSnapshot.docs.length - 1];
// Next page
const nextPageQuery = query(
collection(db, "posts"),
orderBy("createdAt", "desc"),
startAfter(lastVisible),
limit(10)
);
const nextSnapshot = await getDocs(nextPageQuery);import { query, collection, onSnapshot, where } from "firebase/firestore";
// Real-time listener
const q = query(
collection(db, "posts"),
where("author", "==", "userId123")
);
const unsubscribe = onSnapshot(q, (snapshot) => {
console.log("Current posts:", snapshot.docs.length);
snapshot.docChanges().forEach((change) => {
if (change.type === "added") {
console.log("New post:", change.doc.data());
} else if (change.type === "modified") {
console.log("Modified post:", change.doc.data());
} else if (change.type === "removed") {
console.log("Deleted post:", change.doc.data());
}
});
});
// Stop listening
unsubscribe();import { query, where, collection, getDocs } from "firebase/firestore";
// IN query
const q1 = query(
collection(db, "posts"),
where("category", "in", ["tech", "science", "health"])
);
// Array contains
const q2 = query(
collection(db, "posts"),
where("tags", "array-contains", "javascript")
);
// Array contains any
const q3 = query(
collection(db, "posts"),
where("tags", "array-contains-any", ["react", "vue", "angular"])
);import { useEffect, useState } from 'react';
import { query, collection, orderBy, limit, startAfter, getDocs } from "firebase/firestore";
import { db } from './firebase-config';
export function usePaginatedQuery(collectionName, pageSize = 10) {
const [posts, setPosts] = useState([]);
const [lastVisible, setLastVisible] = useState(null);
const [loading, setLoading] = useState(false);
const [hasMore, setHasMore] = useState(true);
const loadMore = async () => {
setLoading(true);
let q;
if (lastVisible) {
q = query(
collection(db, collectionName),
orderBy("createdAt", "desc"),
startAfter(lastVisible),
limit(pageSize)
);
} else {
q = query(
collection(db, collectionName),
orderBy("createdAt", "desc"),
limit(pageSize)
);
}
const snapshot = await getDocs(q);
const newDocs = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
setPosts(prev => [...prev, ...newDocs]);
setLastVisible(snapshot.docs[snapshot.docs.length - 1]);
setHasMore(snapshot.docs.length === pageSize);
setLoading(false);
};
return { posts, loadMore, loading, hasMore };
}import { query, collection, onSnapshot } from "firebase/firestore";
const q = query(collection(db, "posts"));
const unsubscribe = onSnapshot(
q,
(snapshot) => {
console.log("Current documents:", snapshot.size);
},
(error) => {
console.error("Error listening to posts:", error);
}
);import { collection, query, where, aggregate, count } from "firebase/firestore";
// Count documents
const cq = query(
collection(db, "posts"),
where("published", "==", true)
);
const countSnapshot = await aggregate(cq, {
count: count()
});
console.log("Published posts:", countSnapshot.data().count);// โ Good: Create composite index for complex filters
const q = query(
collection(db, "posts"),
where("author", "==", "userId"),
where("published", "==", true),
orderBy("createdAt", "desc")
);
// โ Avoid: Too many subcollection reads
// Instead, denormalize data when appropriate
// โ Good: Use limits to reduce document reads
const q = query(
collection(db, "posts"),
limit(10)
);
// โ Avoid: Reading all documents and filtering
const allPosts = await getDocs(collection(db, "posts"));Explore Realtime Database for alternative synchronization, or implement Firebase Storage for file management.
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep โข Build Real โข Verify Skills โข Launch Forward