🍃 MongoDB Tutorial

MongoDB Evaluation Operators: $expr, $mod, $regex, $text, $where

Learn MongoDB's evaluation query operators — comparing two fields with $expr, modulo matching with $mod, pattern matching with $regex, full-text search with $text, and $where.

MongoDB Evaluation Operators

Evaluation operators let you run more advanced logic against a document's fields — from comparing two fields to each other, to full-text search.

Operator Description
$expr Lets you use aggregation-style expressions inside a query
$mod Matches on the remainder of a division
$regex Matches a field against a regular expression
$text Performs a full-text search on an indexed field
$where Matches documents against a JavaScript expression

$expr — Compare Two Fields

Normal queries compare a field to a literal value. $expr lets you compare two fields on the same document to each other.

db.tripBudget.find({ $expr: { $gt: ['$spent', '$budget'] } })
// documents where spent went over budget

db.tripBudget.find({ $expr: { $lt: ['$spent', '$budget'] } })
// documents that came in under budget

$mod — Modulo

Matches when a field's value, divided by a divisor, leaves the given remainder.

db.tripBudget.find({ spent: { $mod: [4000, 1000] } })
// 21000 / 4000 leaves a remainder of 1000 — matches

$regex — Pattern Matching

MongoDB uses PCRE-style regular expressions for string pattern matching.

db.employees.find({ name: { $regex: 'Gupta' } })
// matches "Gupta" case-sensitively

db.employees.find({ name: { $regex: 'gupta', $options: 'i' } })
// case-insensitive match

// equivalent shorthand using a regex literal:
db.employees.find({ name: /gupta/i })

i makes the match case-insensitive.

$text — Full-Text Search

Requires a text index on the field first.

db.employees.createIndex({ name: "text" })

db.employees.find({ $text: { $search: "Gupta" } })
// text search is case-insensitive by default

db.employees.find({ $text: { $search: "gupta", $caseSensitive: true } })
// nothing returned — "gupta" doesn't exist with that exact case

$where — JavaScript Expressions

Runs a JavaScript function against every document. It's flexible but slower than native operators, since it can't use indexes efficiently.

db.employees.find({
  $where: function () {
    return (obj.city == "Pune")
  }
})

Common Errors & Troubleshooting

  • MongoServerError: text index required for $text query — you tried $text search on a field with no text index — run createIndex({ field: "text" }) first (see the Indexing section).
  • $regex running very slowly on a large collection — a regex with no anchored start (like /gupta/ instead of /^gupta/) can't use a normal index efficiently and forces a full collection scan; anchor patterns at the start whenever possible, or use $text for genuine full-text search instead.
  • Forgetting $options: 'i' and getting zero results — $regex is case-sensitive by default; searching 'gupta' won't match a stored value of 'Gupta' unless you add the case-insensitive option.

Key Takeaways

  • $expr is the only way to compare two fields of the same document to each other.
  • $regex needs $options: 'i' (or a /pattern/i literal) for case-insensitive matches.
  • $text requires a text index to exist first — it will error otherwise.
  • $where is powerful but slow; prefer the other operators when possible.