Skip to content

Firestore Queries — Filtering, Sorting, and Paginating Data with where, orderBy, and limit

DodaTech Updated 2026-06-28 4 min read

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

  1. What is the max documents a query returns without limit?
  2. How do you filter by multiple field conditions?
  3. What is cursor-based pagination and why use it?
  4. When do you need a composite index?
  5. Can you query across multiple collections?

Answers:

  1. 1000 documents.
  2. Use multiple where conditions in the same query, separated by commas.
  3. Pagination using startAfter/startAt instead of offset to avoid reading skipped documents.
  4. When using equality filters on different fields, or range filters with orderBy on different fields.
  5. 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

Can I use != (not equal) queries in Firestore?

Yes, Firestore supports != queries. They work by combining < and > operators and require a composite index.

How do I handle case-insensitive queries?

Firestore queries are case-sensitive. To handle case-insensitive queries, store a lowercase version of the field alongside the original.

What is the performance of collection group queries?

Collection group queries are slightly slower than single collection queries because they scan multiple collections. Ensure proper indexes are created.

Can I use array-contains-any for OR-like queries?

Yes. array-contains-any checks if any value in an array matches any of the specified values, enabling OR-like logic.

How many where clauses can a query have?

A single query can have multiple where clauses, but the combined index requirements and query complexity grows. Limit to 5-10 where clauses for maintainability.

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