The $function operator runs custom JavaScript inside MongoDB aggregation pipelines. When built-in operators are not enough, you can define your own logic with a body, pass values through args, and set lang to "js".
01
Custom JavaScript
Write your own logic.
02
Syntax
body, args, lang.
03
args Array
Pass field values in.
04
$addFields
Add computed results.
05
Use Cases
Grades, formatting, rules.
06
Prefer Native
Use built-ins when possible.
Fundamentals
Definition and Usage
In MongoDB’s aggregation framework, the $function operator executes a JavaScript function for each document. You provide three parts: body (the function code), args (values passed as parameters), and lang (must be "js"). The return value of your function becomes the expression result — useful for custom grading rules, string formatting, or business logic that native operators cannot express cleanly.
💡
Beginner Tip
Your function cannot read this or access the document directly. Pass everything you need through args, like [ "$score", "$name" ]. Parameter order matches the args array order.
Foundation
📝 Syntax
The $function operator takes an object with body, args, and lang:
body — a JavaScript function or a string containing function code.
args — array of expressions (field paths like "$score" or literals) passed as function parameters.
lang — must be "js" (the only supported language).
Use inside stages like $project, $addFields, or $set.
The function must return a value compatible with BSON types.
⚠️
$function vs built-in operators
Custom JavaScript is slower and harder to maintain than native operators like $cond, $switch, or $map. Reach for $function only when built-ins cannot solve the problem. On self-hosted deployments, JavaScript execution may require additional server configuration.
Arrays and numbers from the document are passed as regular JavaScript values. Your function can use loops, conditionals, and any JS logic MongoDB allows.
Example 4 — Function Body as a String
When storing pipelines in config files, a string body can be easier to serialize:
The body string must contain a valid JavaScript function definition. MongoDB parses and executes it the same way as an inline function. Both forms are equivalent at runtime.
Applications
🚀 Use Cases
Custom business rules — grading, tiering, or eligibility logic that goes beyond $cond.
String formatting — build display labels from multiple fields with JavaScript string logic.
Array processing — loop over embedded arrays when $reduce or $map would be awkward.
Prototyping — test complex transformations before refactoring to native operators.
🧠 How $function Works
1
MongoDB evaluates args
Each expression in args is resolved — field paths like "$score" become actual values.
Input
2
JavaScript function runs
MongoDB calls your body function with those values as parameters, in order.
Execute
3
Return value is stored
Whatever your function returns becomes the expression result in $project or $addFields.
Output
=
📊
Custom computed field
Each document gets a value produced by your JavaScript logic.
Wrap Up
Conclusion
The $function operator unlocks custom JavaScript in MongoDB aggregation pipelines. It is powerful for business rules, formatting, and array logic that native operators cannot express cleanly.
For beginners, remember the three parts: body (your function), args (inputs from fields), and lang: "js". Start simple with one argument, then expand as your logic grows — but always check if $cond or $switch can do the job first.
Prefer built-in operators when they are sufficient
Keep functions small and easy to test
Handle null or missing values inside your function
Use string body when storing pipelines in config
❌ Don’t
Use $function for simple logic that $cond handles
Assume the function can access the full document without args
Run heavy loops on large arrays in production without testing
Forget lang: "js" — it is required
Return values that are not valid BSON types
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about $function
Use these points when adding custom JavaScript to pipelines.
5
Core concepts
🔢01
Custom JavaScript
Your logic, your rules.
Purpose
📝02
Three Parts
body, args, lang.
Syntax
🛠03
args Array
Pass field values in.
Usage
🔍04
Complex Rules
Grades, tiers, totals.
Use case
⚠05
Prefer Native
Use built-ins first.
Edge case
❓ Frequently Asked Questions
$function lets you run custom JavaScript inside an aggregation pipeline. You define a function body, pass arguments from document fields or expressions, and return a computed value for each document.
The syntax is { $function: { body: <function or string>, args: [ <expressions> ], lang: "js" } }. The body contains your JavaScript logic, args supplies inputs, and lang must be "js".
Use $function when built-in operators like $cond, $switch, or $map cannot express your logic cleanly. Prefer native operators for performance and portability whenever possible.
Not inside the function body. Pass field values through the args array, such as [ "$score", "$name" ]. The function receives those values as parameters in order.
Use $function inside expression stages such as $project, $addFields, and $set when you need custom per-document computation.