MongoDB $function Operator

Beginner
5 min read
Updated: Oct 2026
3 examples
Live preview

What Is $function?

$function is a MongoDB aggregation expression that runs custom JavaScript for each document. You pass inputs through args, write logic in body, and set lang to "js". Prefer built-in operators when they can do the same job.

Remember
$function = custom JS inside aggregation

{
  $function: {
    body: function(score) { ... },
    args: [ "$score" ],
    lang: "js"
  }
}

args → function parameters (in order)
body → return a value
lang → must be "js"

prefer $cond / $switch when possible
UsePrefer
Custom JS logic in the pipeline$function
Simple if / else$cond
Many branches$switch

How to Use $function in MongoDB

Write a small function, feed it values through args, and emit the return value.

  1. Choose an expression stage ($addFields or $project).
  2. List inputs in args (field paths or expressions).
  3. Write body as a function whose parameters match that order.
  4. Set lang: "js" and return the value you want stored.
PieceRequired?Role
bodyYesJavaScript function (or string form)
argsYesValues passed into the function
langYesMust be "js"

Pseudocode

Pseudocode
for each document:
    values = evaluate each expression in args
    result = run JavaScript body(values...)
    emit { ..., field: result }

Cheat Sheet

Keep these facts handy while writing custom pipeline functions.

TopicDetail
TypeAggregation expression (not a find filter)
Syntax{ $function: { body, args, lang: "js" } }
Field accessOnly via args, not this
PerformanceSlower than native operators
First choice$cond, $switch, math ops
Sample checkscore 85 → grade "B"

Live Preview

Watch a small grading function turn a score into a letter—the same idea as $function below.

Simulates body: function(score) { ... } with args: [score].

Result
score = 85
$function → "B"

{ grade: "B" }

Worked Walkthrough — Letter Grade

Asha scored 85. We want a letter grade with a tiny JavaScript function.

Calculation
Document:
  { name: "Asha", score: 85 }

args: [ 85 ]
body(score):
  if score >= 90 → "A"
  if score >= 80 → "B"
  if score >= 70 → "C"
  else → "F"

85 >= 80 → "B" ✓

MongoDB Examples

We use one student document. First compute a letter grade from score, then build a short message from name and score. Run these in mongosh after inserting the sample data once.

Example 1 — Sample Data

Imagine one student named Asha with score 85. We save that in a collection named students.

mongosh
db.students.insertOne({
  _id: 1,
  name: "Asha",
  score: 85
});

How the Data Is Stored in MongoDB

After the insert, MongoDB keeps one document in students. Run find() to see it:

mongosh
db.students.find()

Read that document like this:

Field in MongoDBValuePlain English
_id1Document id (row number for this lesson)
name"Asha"Student name
score85Numeric test score
Picture
Pipeline passes values into JS:

  args: ["$score"]  →  function(score)
  score = 85
       |
       v
  grade = "B"

How It Works

  1. Insert once. insertOne adds a single student document to students.
  2. Fields stay plain data. name and score are just stored values.
  3. find() shows the same shape. Ready for $function in the next examples.

Example 2 — Letter Grade

Goal: compute grade from score with a small JavaScript function.

mongosh
db.students.aggregate([
  {
    $addFields: {
      grade: {
        $function: {
          body: function (score) {
            if (score >= 90) return "A";
            if (score >= 80) return "B";
            if (score >= 70) return "C";
            return "F";
          },
          args: ["$score"],
          lang: "js"
        }
      }
    }
  }
]);

How It Works

  1. Pass the field in. args: ["$score"] sends 85 into the first parameter.
  2. Run the body. The if chain picks "B" for scores ≥ 80.
  3. Store the return value. $addFields writes grade: "B".

Example 3 — Two Arguments

Same student, but pass both name and score to build a short message.

mongosh
db.students.aggregate([
  {
    $addFields: {
      summary: {
        $function: {
          body: function (name, score) {
            return name + " scored " + score;
          },
          args: ["$name", "$score"],
          lang: "js"
        }
      }
    }
  }
]);

How It Works

  1. Same stored document. Still using Asha and score 85 from Example 1.
  2. Args map by order. First arg → name, second → score.
  3. Return a string. The function concatenates them into "Asha scored 85".

Edge Cases & Pitfalls

Check these before using $function in production pipelines.

args

No direct field access in body

You cannot read $score inside the function. Pass it through args first.

perf

Prefer built-in operators

Native ops like $cond and $switch are faster and easier to maintain for simple logic.

server

Needs server-side JavaScript

Some deployments disable JS. If $function errors, check server settings and Atlas feature support for your tier.

size

Keep the body tiny

Heavy loops or large scripts hurt latency. Move complex work to the application layer when possible.

Performance Notes

ApproachCostBest for
Built-in operatorsLowestMost day-to-day pipeline math/logic
Small $functionHigher per docLogic that is awkward in expression trees
Large JS bodyHighestAvoid on large collections

Filter early with $match so JavaScript runs on fewer documents.

Key Takeaways

  • Role: custom JavaScript inside aggregation.
  • Required: body, args, lang: "js".
  • Inputs: only through args (by parameter order).
  • Default choice: use built-ins first; $function as escape hatch.

One line: $function runs small server-side JS in the pipeline—pass values via args, return a result.

Frequently Asked Questions

$function runs custom JavaScript inside an aggregation pipeline. You supply a function body, an args array of inputs, and lang: "js". The return value becomes the expression result for each document.
Use { $function: { body: <function or string>, args: [ <expressions> ], lang: "js" } }. body holds the JavaScript, args passes values into the function parameters in order, and lang must be "js".
No. Pass field values through args, such as [ "$score", "$name" ]. Inside the function those values arrive as parameters.
Use it when built-in operators cannot express the logic cleanly. Prefer native operators like $cond or $switch for speed and simpler maintenance whenever possible.
It is usually slower than equivalent built-in expressions because the server runs JavaScript per document. Keep bodies small and avoid it on hot paths when a native operator works.
Inside expression stages such as $project, $addFields, and $set for per-document custom computation.

Next: $getField

Read a document field when the field name is computed dynamically.

$getField tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

9 people found this page helpful