Query Operators
Introduction
Equality filters cover simple cases; real queries need comparison, logic, array, and element operators. MongoDB prefixes operators with $. This chapter builds expressive filters on posts and users collections—the foundation for analytics, admin search, and API query parameters.
Prerequisites
- Find Queries and Projection
- Sample
hello_demo.postsandhello_demo.usersdata
Comparison Operators
// Greater than / less than
db.posts.find({ viewCount: { $gt: 50 } })
db.posts.find({ viewCount: { $gte: 50, $lte: 200 } })
// Not equal
db.posts.find({ published: { $ne: false } })
// Explicit equality (optional)
db.posts.find({ published: { $eq: true } })| Operator | Meaning |
|---|---|
$eq | Equal |
$ne | Not equal |
$gt, $gte, $lt, $lte | Comparisons |
Dates compare chronologically when stored as Date:
db.posts.find({
createdAt: { $gte: new Date("2026-02-01"), $lt: new Date("2026-03-01") }
})Logical Operators
Element Operators
// Field exists
db.users.find({ email: { $exists: true } })
// Missing optional field
db.users.find({ phone: { $exists: false } })
// BSON type check — type 2 = string, 10 = null, etc.
db.posts.find({ title: { $type: "string" } })
db.posts.find({ title: { $type: ["string", "null"] } })Array Operators
Seed users with tags:
db.users.insertOne({
name: "Bob",
tags: ["reader", "author", "mongodb"]
})Queries:
Regular Expressions
// Case-insensitive title contains "mongo"
db.posts.find({ title: { $regex: /mongo/i } })
// Prefix search — can use index if anchored ^mongo
db.posts.find({ slug: { $regex: "^index" } })Warning
Regex Performance
Unanchored regex often causes COLLSCAN. Prefer text indexes or anchored prefixes — Indexes.
Dot Notation and Nested Queries
db.users.find({ "address.country": "UK" })
db.users.find({ "address.city": { $in: ["London", "Manchester"] } })Combining Operators in APIs
Map query params to filters carefully—validate types to prevent injection-style bugs:
// Safe pattern in app code: build filter object from validated input
// { published: true, viewCount: { $gte: minViews } }Driver parameterization still uses BSON objects—not string concatenation.
Operator Quick Reference
| Use case | Operator |
|---|---|
| Range | $gt, $gte, $lt, $lte |
| Multiple OR | $or, $in |
| Exclude values | $nin, $ne |
| Optional field | $exists |
| Array contains | $all, $elemMatch |
| Pattern match | $regex |
Common Mistakes
| Mistake | Fix |
|---|---|
{ tags: { $in: "a" } } wrong shape | $in needs array: { $in: ["a"] } |
String date vs Date | Parse to Date in app |
$where with JavaScript | Deprecated/slow—use standard operators |
Overly complex $or without indexes | Add compound indexes — chapter 11 |
Post-Chapter Checklist
- Comparison and logical operators on
posts -
$in,$all,$elemMatchon arrays -
$existsand$type - You know regex index pitfalls
FAQ
Implicit AND vs $and?
Multiple top-level fields are ANDed. Use $and when you need two conditions on the same field.
Query empty array?
{ tags: [] } matches documents where tags is empty array.
Case-insensitive exact match?
Collation with strength: 2 or normalize case in app—not only regex.
SQL IN (...)?
{ field: { $in: [1, 2, 3] } }
Not operator on regex?
{ name: { $not: /test/i } }