Query performance in a Criteria-based codebase follows the same fundamental rules as any MongoDB application — the library translates yourDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/abejarano/ts-mongo-criteria/llms.txt
Use this file to discover all available pages before exploring further.
Criteria objects into standard find calls, so every MongoDB index, query shape, and execution-plan principle applies directly. This guide covers the most impactful optimisations, from index design to pagination patterns, with concrete ensureIndexes examples and real monitoring snippets.
Index Strategy
Well-designed indexes are the single biggest lever for query performance. Create them once inensureIndexes so they are always in place when the collection is first accessed.
Single-field indexes
Use single-field indexes for columns that appear frequently in equality or range filters:Compound indexes
Compound indexes support queries that combine multiple filter and sort fields. Field order matters: put equality filters first, range filters next, and the sort field last.Text indexes for CONTAINS / NOT_CONTAINS
When aCriteria uses Operator.CONTAINS or NOT_CONTAINS, MongoDB runs a regex scan unless a text index is available. Create a text index on every field you search:
Filter Ordering
The order you pass filters toCriteria influences which query plan MongoDB chooses. Place filters in this order for the best results:
- Most selective equality filters first (unique IDs, email addresses)
- Lower-selectivity equality filters (status, category, role)
- Range filters (age, price, date windows)
- Text / OR filters last — these are the most expensive
Pagination
Standard offset pagination
Criteria accepts limit and page as its third and fourth arguments. MongoDB implements this as skip((page-1)*limit).limit(limit), which is efficient for small page numbers.
Deep pagination warning
Each additional page requires MongoDB to scan and discard(page-1)*limit documents before returning results. Page 1 000 with a limit of 20 causes a skip of 19 980 — even with an index, this is expensive at scale.
Cursor-based pagination for large datasets
Replace the page number with a range filter on the sort key to implement efficient cursor-based (keyset) pagination:Limiting OR conditions
OR filters (Operator.OR) are expanded into a MongoDB $or array. A small number of conditions (3–5) uses the index union efficiently; beyond 10 conditions, MongoDB may fall back to a collection scan.
fieldsToExclude
Pass an array of field names as the second argument tolist() to project out fields you do not need. This reduces the bytes transferred from MongoDB to your application server.
Performance monitoring
Wraplist() calls with a simple timing helper to surface slow queries in your logs or APM tool:
Common issues
Collection scan (COLLSCAN)
Collection scan (COLLSCAN)
Symptom: Queries are slow on large collections and Then verify with
explain() shows COLLSCAN in the winning plan.Cause: No index covers the filter field(s) used in your Criteria.Fix: Add the missing index in ensureIndexes:db.collection.explain("executionStats").find(yourFilter) that the stage changes from COLLSCAN to IXSCAN.Inefficient text search (regex without text index)
Inefficient text search (regex without text index)
Symptom: For more than five fields, consider denormalising into a single
Operator.CONTAINS queries are slow; explain() shows a COLLSCAN with a $regex filter.Cause: The fields targeted by CONTAINS / OR do not have a MongoDB text index, so every document must be scanned and tested with a regex.Fix: Create a text index covering all searched fields:searchText field and indexing only that field to keep the text index compact.Deep pagination (large page numbers)
Deep pagination (large page numbers)
Symptom: Response times increase linearly with the page number; page 500+ is noticeably slow.Cause: MongoDB implements offset pagination as a
skip(n) — it must traverse and discard n index entries before returning results.Fix: Switch to cursor-based pagination for datasets where users need to scroll beyond the first 50–100 pages. Use a range filter on the sort key instead of a page number (see the Pagination section above).Sorting without a supporting index (in-memory sort)
Sorting without a supporting index (in-memory sort)
Symptom:
explain() shows a SORT stage with memLimit warnings; queries occasionally fail with a “sort exceeded memory limit” error.Cause: The field passed to Order.desc() / Order.asc() is not the last field of the compound index that covers the query.Fix: Ensure the compound index ends with the sort field in the correct direction: