The $where operator runs a JavaScript expression against each document in a find() query. It is a legacy query operator — useful to understand for reading old code, but modern MongoDB apps should prefer $expr and native operators instead.
01
JS Filter
Custom logic.
02
this Keyword
Current document.
03
String or Fn
Two syntax forms.
04
find() Only
Query operator.
05
Deprecated
Use $expr instead.
06
Security
Avoid user input.
Fundamentals
Definition and Usage
In MongoDB, the $where operator is a query operator that evaluates a JavaScript expression for every document in a collection. If the expression returns true, the document is included in the result set. Inside the script, this refers to the current document, so you can write conditions like this.qty * this.price > 1000.
MongoDB deprecated$where in version 4.4 because it forces a collection scan, cannot use indexes effectively, and introduces security risks when user input is embedded in JavaScript strings. For new projects, use $expr with aggregation operators such as $multiply, $gt, and $eq.
💡
Beginner Tip
Learn $where to read legacy tutorials and old codebases, but write new queries with $expr. Native operators are faster, safer, and easier to maintain.
Foundation
📝 Syntax
$where accepts either a JavaScript string or a function:
$expr lets you use aggregation expression operators in query filters. This is the pattern MongoDB recommends instead of $where.
Bonus — Security: Never Build $where from User Input
This pattern is dangerous and should never be used in production:
mongosh
// DANGEROUS — do not do this:
var userInput = "1000; return true"; // malicious input
db.products.find({
$where: "this.qty * this.price > " + userInput
})
// SAFE — use parameterized $expr instead:
var threshold = 1000;
db.products.find({
$expr: {
$gt: [
{ $multiply: ["$qty", "$price"] },
threshold
]
}
})
How It Works
Concatenating user input into a JavaScript string can allow code injection. Native operators with bound values avoid executing arbitrary scripts.
Applications
🚀 Use Cases
Legacy codebases — understand and migrate old queries that still use $where.
Field comparisons — filter when one field must be greater than another (prefer $expr today).
Complex conditions — prototype logic quickly in tutorials (rewrite with native operators for production).
One-off admin scripts — ad hoc filtering on small collections during data exploration.
🧠 How $where Works
1
MongoDB scans documents
Each document in the collection is considered as a candidate match.
Scan
2
JavaScript runs on each doc
The $where string or function executes with this bound to the current document.
Evaluate
3
Truthy results are kept
Documents where the expression returns true pass the filter and appear in query results.
Filter
=
🔍
Custom-filtered set
For production, achieve the same outcome with $expr and native operators.
Wrap Up
Conclusion
The $where operator lets you filter documents with JavaScript in find() queries. It is useful for understanding legacy MongoDB code, but it is deprecated because of performance and security concerns.
For new development, use $expr with aggregation operators. For custom JavaScript inside pipelines (not ad hoc query filters), see $function. Next in the series: $year.
Rewrite $where queries as $expr when migrating legacy code
Use native operators like $multiply, $gt, and $size
Limit $where to small collections in one-off scripts only
Document why a legacy query used JavaScript if you cannot migrate yet
Use $function for controlled JS inside aggregation pipelines
❌ Don’t
Use $where in new production application code
Concatenate user input into $where JavaScript strings
Run $where on large collections expecting fast performance
Assume indexes will speed up $where filters
Confuse query $where with pipeline $function
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about $where
Use these points when reading or migrating legacy MongoDB queries.
5
Core concepts
📝01
JS Filter
find() queries.
Purpose
🛠02
this.field
Current document.
Syntax
⚠03
Deprecated
Since MongoDB 4.4.
Status
🔄04
Use $expr
Modern replacement.
Migrate
🔒05
No User Input
Injection risk.
Security
❓ Frequently Asked Questions
$where runs a JavaScript expression against each document in a find() query. The expression must return true to include the document. Inside the script, this refers to the current document.
You can pass a string: { $where: "this.qty * this.price > 1000" } or a function: { $where: function() { return this.qty * this.price > 1000; } }. Use find() or $match in rare legacy cases.
No. MongoDB deprecated $where in version 4.4 because it is slow, cannot use indexes efficiently, and poses security risks. Prefer $expr with aggregation operators like $multiply, $gt, and $eq instead.
this refers to the current document being evaluated. You can read fields with this.fieldName, such as this.price or this.tags.length.
Use $expr in find() or aggregation $match: { $expr: { $gt: [ { $multiply: ["$qty", "$price"] }, 1000 ] } }. Native operators are faster, index-friendly where possible, and avoid arbitrary JavaScript.