DocsHub
Querying

Evaluation Operators

Learn how to query documents using $regex for pattern matching, $expr for comparing fields, and $text for full-text search.

Evaluation Operators

Evaluation operators go beyond simple value comparisons. They let you match documents based on patterns, compare fields against each other, and run full-text searches.

  • $regex — match a field against a regular expression pattern
  • $expr — compare fields within the same document using expressions
  • $text — run a full-text search across indexed string fields

$regex

$regex matches documents where a string field matches a regular expression pattern. Use it when you need to search by partial text, pattern, or case-insensitive match.

Syntax

db.collection.find({ field: { $regex: /pattern/ } })
// or
db.collection.find({ field: { $regex: "pattern", $options: "i" } })

Example — Find students whose name starts with "Ali"

db.students.find({ name: { $regex: /^Ali/ } })

The ^ means "starts with". This returns Ali Hassan, Ali Ahmed, and so on.

Example — Find students whose name ends with "Khan"

db.students.find({ name: { $regex: /Khan$/ } })

The $ means "ends with".

Example — Find students whose name contains "ahmed" — case insensitive

db.students.find({
  name: { $regex: /ahmed/i }
})

The i flag makes the match case-insensitive. This returns Ahmed, ahmed, AHMED — all variations.

Using $options

You can also write the pattern as a string and pass options separately:

db.students.find({
  name: { $regex: "ahmed", $options: "i" }
})

Common $options flags:

FlagMeaning
iCase-insensitive match
mMultiline — ^ and $ match start and end of each line
sAllows . to match newline characters
xIgnore whitespace in the pattern

Example — Find courses whose title contains "science"

db.courses.find({
  title: { $regex: /science/i }
})

This returns "Computer Science", "Social Science", "Science" — anything containing the word.

Example — Find teachers whose email is from a specific domain

db.teachers.find({
  email: { $regex: /@school\.com$/ }
})

$regex queries on large collections without an index are slow — MongoDB has to scan every document and test the pattern. For heavy text search needs, use a text index with $text instead. Use $regex for simple pattern matching on small collections or indexed fields.


$expr

$expr lets you compare two fields within the same document using aggregation expressions. Regular query operators compare a field against a fixed value — $expr compares a field against another field.

Syntax

db.collection.find({
  $expr: { $operator: ["$field1", "$field2"] }
})

Notice the $ prefix on field names inside $expr — this tells MongoDB to treat them as field references, not literal strings.

Example — Find courses where totalStudents exceeds capacity

Imagine courses have both a totalStudents field and a capacity field:

db.courses.find({
  $expr: { $gt: ["$totalStudents", "$capacity"] }
})

This finds courses where totalStudents is greater than capacity — comparing two fields in the same document. You cannot do this with regular $gt because $gt compares a field against a fixed value, not another field.

Example — Find students where their exam score is greater than their assignment score

db.students.find({
  $expr: { $gt: ["$examScore", "$assignmentScore"] }
})

Example — Find students whose age matches their expected grade year

// Students where age minus 5 equals their school year number
db.students.find({
  $expr: {
    $eq: [
      { $subtract: ["$age", 5] },
      "$schoolYear"
    ]
  }
})

$expr supports all aggregation expressions — $add, $subtract, $multiply, $divide, and more. We cover these in depth in the Aggregation section.

Example — Find students where first semester score is higher than second semester

db.students.find({
  $expr: { $gt: ["$semester1Score", "$semester2Score"] }
})

$expr is a bridge between the query layer and the aggregation layer. If you find yourself needing to compare fields or do calculations inside a query filter, $expr is the tool for the job.


$text

$text performs a full-text search on fields that have a text index. It is designed for searching natural language content — like searching for a word or phrase across a name or description field.

Step 1 — Create a text index

Before you can use $text, you must create a text index on the field you want to search:

// Create a text index on the name field
db.students.createIndex({ name: "text" })

// Create a text index on multiple fields
db.courses.createIndex({ title: "text", description: "text" })

We cover indexes in depth in the Indexes section. For now, just know that $text requires one.

Step 2 — Search with $text

// Find students whose name contains "Hassan"
db.students.find({
  $text: { $search: "Hassan" }
})

Syntax

db.collection.find({
  $text: {
    $search: "search terms",
    $caseSensitive: false,      // optional — default is false
    $diacriticSensitive: false  // optional — default is false
  }
})

Searching multiple words

When you pass multiple words, $text returns documents that contain any of those words (OR behavior):

// Find courses that mention "Math" OR "Science"
db.courses.find({
  $text: { $search: "Math Science" }
})

Searching an exact phrase

Wrap the phrase in escaped quotes to search for an exact phrase:

// Find courses with the exact phrase "Computer Science"
db.courses.find({
  $text: { $search: "\"Computer Science\"" }
})

Excluding a word

Prefix a word with - to exclude documents that contain it:

// Find courses that mention "Science" but NOT "Computer"
db.courses.find({
  $text: { $search: "Science -Computer" }
})

Sorting by relevance score

$text search assigns each result a relevance score. You can sort by it to show the most relevant results first:

db.courses.find(
  { $text: { $search: "Math Science" } },
  { score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } })

$text is much faster than $regex for searching text content because it uses an index. For any feature where users search by keyword — like a search bar — always use $text with a text index instead of $regex.


$regex vs $text — When to Use Which

$regex$text
Requires indexNoYes — text index required
Speed on large collectionsSlowFast
Pattern matching✅ Yes❌ No
Partial word match✅ Yes❌ No — whole words only
Multi-field search❌ One field at a time✅ Yes — across all text-indexed fields
Relevance scoring❌ No✅ Yes
Best forPatterns, formats, small dataKeyword search, search bars

School System Examples

// Find students whose name starts with "Ali"
db.students.find({ name: { $regex: /^Ali/i } })

// Find students whose name contains "ahmed" — any case
db.students.find({ name: { $regex: /ahmed/i } })

// Find teachers with a school.com email
db.teachers.find({ email: { $regex: /@school\.com$/i } })

// Find courses whose title contains "science" — any case
db.courses.find({ title: { $regex: /science/i } })

// Find courses where totalStudents exceeds capacity
db.courses.find({
  $expr: { $gt: ["$totalStudents", "$capacity"] }
})

// Find students where exam score is higher than assignment score
db.students.find({
  $expr: { $gt: ["$examScore", "$assignmentScore"] }
})

// Full text search — create index first
db.courses.createIndex({ title: "text", description: "text" })

// Search for courses mentioning "computer"
db.courses.find({ $text: { $search: "computer" } })

// Search for exact phrase
db.courses.find({ $text: { $search: "\"computer science\"" } })

// Search and sort by relevance
db.courses.find(
  { $text: { $search: "math science" } },
  { score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } })

Quick Reference

OperatorWhat it doesExample
$regexMatch a pattern in a string field{ name: { $regex: /^Ali/i } }
$exprCompare two fields in the same document{ $expr: { $gt: ["$score1", "$score2"] } }
$textFull-text search on text-indexed fields{ $text: { $search: "math" } }

For a student-facing search feature in your school app — like searching for a course by name — create a text index and use $text. It is faster, smarter, and supports relevance scoring. Save $regex for internal tools and admin queries where you need pattern matching.

On this page