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

Comparison Operators

javascript
// 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 } })
OperatorMeaning
$eqEqual
$neNot equal
$gt, $gte, $lt, $lteComparisons

Dates compare chronologically when stored as Date:

javascript
db.posts.find({
  createdAt: { $gte: new Date("2026-02-01"), $lt: new Date("2026-03-01") }
})

Logical Operators

Element Operators

javascript
// 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:

javascript
db.users.insertOne({
  name: "Bob",
  tags: ["reader", "author", "mongodb"]
})

Queries:

Regular Expressions

javascript
// 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

javascript
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:

javascript
// 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 caseOperator
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

MistakeFix
{ tags: { $in: "a" } } wrong shape$in needs array: { $in: ["a"] }
String date vs DateParse to Date in app
$where with JavaScriptDeprecated/slow—use standard operators
Overly complex $or without indexesAdd compound indexes — chapter 11

Post-Chapter Checklist

  • Comparison and logical operators on posts
  • $in, $all, $elemMatch on arrays
  • $exists and $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 } }