Comparison Operators: $eq, $gt, $lt, $in
Learners will use comparison operators to filter documents by numeric ranges, exact matches, and membership in a list.
Comparison Operators: $eq, $gt, $lt, $in is a free MongoDB Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the MongoDB Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Beyond Equality Filters
Simple equality filters like { status: 'active' } are useful, but real queries need more nuance. MongoDB provides a rich set of query operators prefixed with $ that express conditions beyond simple equality. These operators let you filter by numeric ranges, membership in a list, value presence, and pattern matching.
Comparison operators are the most commonly used category. They work on any comparable BSON type: numbers, strings (lexicographic comparison), dates, and even ObjectIds (chronological order, since ObjectIds encode timestamps).
$eq: Explicit Equality
The $eq operator explicitly tests for equality: { age: { $eq: 30 } }. In most cases, the shorthand { age: 30 } is identical and preferred for readability—$eq is mainly useful when the operator is needed inside another expression like $expr.
One difference: $eq inside aggregation pipeline expressions is required when comparing two field values (e.g., { $eq: ['$price', '$salePrice'] }). In regular find filters, stick to the shorthand equality syntax unless a specific context requires the operator form.
// These two queries are equivalent in find()
db.users.find({ age: 30 });
db.users.find({ age: { $eq: 30 } });
// $eq is useful inside $expr for field-to-field comparison:
db.products.find({
$expr: { $eq: ['$price', '$salePrice'] }
});
// Returns products where price equals salePrice$gt and $gte: Greater Than
$gt (greater than) and $gte (greater than or equal) filter documents where a field's value exceeds a threshold. These work on numbers, dates, strings (lexicographic order), and ObjectIds.
Date comparisons are particularly powerful: { createdAt: { $gte: new Date('2024-01-01') } } finds all documents created since January 1, 2024. This query can use an index on createdAt for O(log n) performance, making date-range queries extremely efficient even on large collections.
// Numeric range
db.products.find({ price: { $gt: 100 } });
// price > 100
db.employees.find({ salary: { $gte: 50000 } });
// salary >= 50000
// Date comparison
db.orders.find({
createdAt: { $gte: new Date('2024-01-01') }
});
// Orders placed since Jan 1, 2024
// String comparison (lexicographic)
db.users.find({ lastName: { $gte: 'M' } });
// Last names starting with M-Z$lt and $lte: Less Than
$lt (less than) and $lte (less than or equal) are the complements of $gt/$gte. Combine both operators on the same field to create a range query—MongoDB applies both conditions to the same field, equivalent to SQL's BETWEEN.
Range queries on indexed fields are very efficient because MongoDB can seek to the lower bound in the index and scan forward to the upper bound, touching only the relevant entries. This is one of the primary reasons to index fields you frequently filter by range.
// Price < 50
db.products.find({ price: { $lt: 50 } });
// Age <= 17 (minors)
db.users.find({ age: { $lte: 17 } });
// Range query: price between 20 and 100 (inclusive)
db.products.find({ price: { $gte: 20, $lte: 100 } });
// Equivalent SQL: WHERE price BETWEEN 20 AND 100
// Date range: orders placed last week
const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
db.orders.find({ createdAt: { $gte: weekAgo, $lte: new Date() } });$ne: Not Equal
$ne (not equal) matches documents where a field's value is not equal to the specified value. It also matches documents where the field does not exist at all—because a missing field is implicitly not equal to any value.
Be cautious with $ne on large, unindexed collections: MongoDB typically cannot use an index to satisfy a negation efficiently and may fall back to a collection scan. For heavily filtered queries, prefer positive conditions ($eq, $in) over negative ones when possible.
// Find orders that are not cancelled
db.orders.find({ status: { $ne: 'cancelled' } });
// Find users who have NOT set a display name
// ($ne also matches missing field)
db.users.find({ displayName: { $ne: null } });
// Caution: $ne on non-indexed field scans full collection
// Index the field if used frequently:
db.orders.createIndex({ status: 1 });
db.orders.find({ status: { $ne: 'cancelled' } }); // Uses index$in: Match Any Value in a List
$in matches documents where a field's value equals any value in a provided array. It is the MongoDB equivalent of SQL's IN clause. This is far more concise than writing multiple $or conditions for the same field.
On an indexed field, $in is implemented as multiple point lookups in the index tree—one per value in the array—which is very efficient. For large lists (hundreds of values), performance degrades, but for typical use cases (5-20 values), $in is a great choice.
// Find products in specific categories
db.products.find({
category: { $in: ['Electronics', 'Computers', 'Peripherals'] }
});
// Equivalent SQL: WHERE category IN ('Electronics', 'Computers', 'Peripherals')
// Find orders with specific statuses
db.orders.find({
status: { $in: ['pending', 'processing', 'shipped'] }
});
// $in on array field: matches if arrays share any element
db.products.find({
tags: { $in: ['sale', 'clearance'] }
}); // Products with 'sale' OR 'clearance' in their tags array$nin: Not In a List
$nin (not in) is the negation of $in—it matches documents where the field's value is not in the provided array (and also matches documents where the field is absent). Like $ne, it can be less efficient than $in because it often requires scanning documents.
A practical use case: excluding a known set of IDs. If a user has blocked certain other users, you might exclude their content: { authorId: { $nin: blockedUserIds } }. Keep the exclusion list small for best performance.
// Exclude archived and deleted statuses
db.tickets.find({
status: { $nin: ['archived', 'deleted', 'spam'] }
});
// Exclude a user's own posts from their feed
const blockedIds = [ObjectId('...'), ObjectId('...')] ;
db.posts.find({
authorId: { $nin: blockedIds }
}).sort({ createdAt: -1 }).limit(20);Combining Comparison Operators
You can combine multiple comparison operators on the same field or different fields in a single query. When operators appear on the same field in one object, they act as an implicit AND—both conditions must be true. When they are on different fields, both conditions must also be true.
Build complex filters by thinking about each field independently and combining conditions. MongoDB evaluates all field conditions together, using indexes where available to minimize the documents examined.
// Products priced between $20-$100, in stock, created this year
const thisYear = new Date('2024-01-01');
db.products.find({
price: { $gte: 20, $lte: 100 }, // Range on price
stock: { $gt: 0 }, // In stock
category: { $in: ['Electronics', 'Home'] }, // Category filter
createdAt: { $gte: thisYear } // Created this year
}).sort({ price: 1 });Comparison Operators on Dates
Date comparisons are among the most common uses of comparison operators in real applications. MongoDB's Date BSON type stores dates as 64-bit milliseconds, so all comparison operators work naturally on date fields.
Common patterns include: finding records created in the last N days, filtering active subscriptions that expire after today, and range queries for reporting periods. Always construct Date objects in the query—never compare dates as strings, as lexicographic string comparison gives incorrect results for most date formats.
// Records created in the last 30 days
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
db.events.find({ createdAt: { $gte: thirtyDaysAgo } });
// Subscriptions that expire in the future (still active)
db.subscriptions.find({ expiresAt: { $gt: new Date() } });
// Orders placed on a specific day (date range for one day)
const startOfDay = new Date('2024-06-01T00:00:00Z');
const endOfDay = new Date('2024-06-01T23:59:59.999Z');
db.orders.find({ createdAt: { $gte: startOfDay, $lte: endOfDay } });Performance: Indexes and Comparison Queries
Comparison operators benefit enormously from indexes. An index on a numeric field turns an O(n) scan into O(log n + result size). Key points:
- Range queries (
$gt,$lt) can use a single-field index to navigate directly to the range start $inperforms multiple point lookups in the index—one per value- Negation operators (
$ne,$nin) often scan the index rather than using point lookups, so they are less efficient - Use
explain('executionStats')to verify your comparison queries use IXSCAN and not COLLSCAN
// Verify range query uses index
db.products.find({ price: { $gte: 20, $lte: 100 } })
.explain('executionStats');
// Look for: winningPlan.stage = 'IXSCAN'
// If COLLSCAN: add index with db.products.createIndex({ price: 1 })
// Create compound index for combined filter:
db.products.createIndex({ category: 1, price: 1 });
// Supports: { category: 'Electronics', price: { $gte: 50 } }Using Comparison Operators With Aggregation
Comparison operators appear in two contexts: as query operators in find() filters (with the syntax { field: { : value } }) and as expression operators in the aggregation pipeline and stages (with a different syntax: { : ['', value] }).
In , expression operators return a boolean or a computed value. For example, you can add a computed field isExpensive that is true when price exceeds 100: { : { isExpensive: { : ['', 100] } } }. The stage uses the same query syntax as find().
// Comparison in aggregation pipeline:
db.products.aggregate([
// uses same syntax as find()
{ : { price: { : 20, : 100 } } },
// uses expression operator syntax:
{
: {
isExpensive: { : ['', 80] }, // Returns boolean
discountedPrice: { : ['', 0.9] } // Computes value
}
}
]);Quick Check
Test your understanding of MongoDB & NoSQL Databases concepts from this lesson.
Lesson Recap
In this lesson you learned: $gt/$gte/$lt/$lte create range conditions on numbers, dates, and strings, and work with indexes for O(log n) range scans, $in matches any value from a list and is significantly more readable and efficient than multiple $or equality conditions on the same field, and $ne/$nin are negation operators that match anything outside the given value/list but are less index-efficient than their positive counterparts. Next up we explore logical operators—$and, $or, $nor, and $not—to combine conditions across different fields.
Frequently asked questions
Is the “Comparison Operators: $eq, $gt, $lt, $in” lesson free?
Yes — the full text of “Comparison Operators: $eq, $gt, $lt, $in” is free to read here on the web, and the MongoDB Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the MongoDB Academy course, upgrade to CoddyKit PRO.
What will I learn in “Comparison Operators: $eq, $gt, $lt, $in”?
Learners will use comparison operators to filter documents by numeric ranges, exact matches, and membership in a list. You practise MongoDB Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start MongoDB Academy?
No prior experience is required. MongoDB Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Comparison Operators: $eq, $gt, $lt, $in” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this MongoDB Academy lesson?
Yes. Every MongoDB Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Comparison Operators: $eq, $gt, $lt, $in
- Logical Operators: $and, $or, $nor, $not
- Element Operators and Type Checks
- Regex Queries and Pattern Matching