MongoDB $cmp Operator

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

What Is $cmp?

$cmp is a MongoDB aggregation expression that compares two values and returns a three-way result: -1 (less), 0 (equal), or 1 (greater). It uses BSON comparison order when types differ.

Remember
$cmp = three-way compare for aggregation

{ $cmp: [ <a>, <b> ] }

a < b  → -1
a = b  →  0
a > b  →  1

$cmp([200, 250]) → -1
$cmp([250, 250]) →  0
$cmp([300, 250]) →  1

true/false checks → prefer $lt / $eq / $gt
UsePrefer
Three-way result (-1 / 0 / 1)$cmp
True/false less or greater$lt / $gt
True/false equality$eq

How to Use $cmp in MongoDB

Pass two expressions in an array, then branch or project on the -1 / 0 / 1 result.

  1. Choose an expression stage ($project or $addFields).
  2. Build { $cmp: [ left, right ] } with fields or literals.
  3. Read -1, 0, or 1 as “less”, “equal”, or “greater”.
  4. Optionally map that result with $switch into labels.
PieceRequired?Role
$cmpYesThree-way compare → -1 / 0 / 1
Two expressionsYesLeft and right values to compare
$switchNoTurn the code into below / exact / above labels

Pseudocode

Pseudocode
for each document:
    a = evaluate(expression1)
    b = evaluate(expression2)
    // missing fields behave like null
    if a < b (BSON order):
        result = -1
    else if a > b (BSON order):
        result = 1
    else:
        result = 0
    emit { ..., field: result }

Cheat Sheet

Keep these facts handy while writing comparison expressions.

TopicDetail
TypeAggregation expression (not a find filter)
Syntax{ $cmp: [ <a>, <b> ] }
Returns-1, 0, or 1
OrderBSON type + value comparison order
Missing fieldTreated like null
Sample check$cmp(["$qty", 250]) vs stock threshold
Boolean siblings$lt, $eq, $gt

Live Preview

Watch $cmp return -1, 0, or 1 for a quantity versus the target 250.

Simulates { $cmp: ["$qty", 250] } (same idea as the mongosh examples below).

Result
qty = 250, target = 250
$cmp([qty, 250]) → 0

{ qty: 250, cmpTo250: 0 }

Worked Walkthrough — Stock Versus 250

Same threshold for every item. The only question is whether qty is below, equal to, or above 250.

Calculation
Target = 250

qty 200:  200 < 250  → $cmp → -1  (below)
qty 250:  250 = 250  → $cmp →  0  (exact)
qty 300:  300 > 250  → $cmp →  1  (above)

Remember the order of arguments:
  $cmp([ "$qty", 250 ])  // qty first, target second
  not the other way around

MongoDB Examples

We store three inventory items, compare each qty to 250, then label the result with $switch. Run these in mongosh after inserting the sample data once.

Example 1 — Sample Data

Imagine a tiny inventory collection with three products. One is below 250, one matches, and one is above.

mongosh
db.inventory.insertMany([
  { _id: 1, item: "pens",  qty: 300 },
  { _id: 2, item: "pads",  qty: 200 },
  { _id: 3, item: "clips", qty: 250 }
]);

How the Data Is Stored in MongoDB

After the insert, MongoDB keeps three documents in inventory. Run find() to see them:

mongosh
db.inventory.find()

Read those documents like this:

Field in MongoDBValuePlain English
_id1 … 3Document id for this lesson
item"pens", "pads", "clips"Product name
qty300, 200, 250Stock count we will compare to 250
Picture
Expected $cmp(["$qty", 250]) results:

  pens  300 →  1
  pads  200 → -1
  clips 250 →  0

How It Works

  1. Insert once. insertMany adds three inventory documents.
  2. Quantities differ on purpose. You get one below, one equal, and one above the target.
  3. find() shows the same shape. What you inserted is what you get back—ready for $cmp next.

Example 2 — Compare to 250

Goal: project each item with $cmp against the threshold 250.

mongosh
db.inventory.aggregate([
  {
    $project: {
      item: 1,
      qty: 1,
      cmpTo250: { $cmp: ["$qty", 250] },
      _id: 0
    }
  }
]);

How It Works

  1. Read qty. Left side is "$qty"; right side is the literal 250.
  2. Compare once per document. $cmp returns 1, -1, or 0.
  3. Keep useful fields. $project keeps item and qty, drops _id for a short report.
  4. Argument order matters. Swapping sides would flip every -1 and 1.

Example 3 — Label with $switch

Same comparison, but map -1 / 0 / 1 into readable stock labels.

mongosh
db.inventory.aggregate([
  {
    $project: {
      item: 1,
      qty: 1,
      stockLevel: {
        $switch: {
          branches: [
            {
              case: { $eq: [{ $cmp: ["$qty", 250] }, -1] },
              then: "below"
            },
            {
              case: { $eq: [{ $cmp: ["$qty", 250] }, 0] },
              then: "exact"
            },
            {
              case: { $eq: [{ $cmp: ["$qty", 250] }, 1] },
              then: "above"
            }
          ],
          default: "unknown"
        }
      },
      _id: 0
    }
  }
]);

How It Works

  1. Compare first. Each branch runs $cmp: ["$qty", 250].
  2. Match the code. $eq checks whether that result is -1, 0, or 1.
  3. Pick a label. $switch returns "below", "exact", or "above".
  4. Easy check. Pads 200 → below, clips 250 → exact, pens 300 → above.

Edge Cases & Pitfalls

Check these before using $cmp in production pipelines.

order

Argument order flips the sign

$cmp([a, b]) is not the same as $cmp([b, a]). Keep “value first, threshold second” consistent.

types

Different types still compare

$cmp uses BSON order across types. A string and a number are comparable, but the result may surprise you—normalize types when needed.

null

Missing fields act like null

A missing qty compared with 250 returns -1 (null < number), not an error. Filter or default first if that is wrong for your app.

boolean

Need true/false? Use $lt / $eq / $gt

Do not force $cmp into boolean logic. Prefer $lt, $eq, or $gt for simple predicates.

Performance Notes

ApproachCostBest for
$cmp alonePer-document compareThree-way codes in reports
$cmp + $switchStill O(docs)Human-readable below/exact/above labels
$gt / $lt insteadSimilar cost, boolean resultSimple true/false filters

Comparison expressions are cheap compared with large sorts or joins. Filter early with $match when only some documents need a compare.

Key Takeaways

  • Role: three-way compare → -1 / 0 / 1.
  • Syntax: { $cmp: [a, b] }.
  • Labels: pair with $switch for below/exact/above.
  • Booleans: prefer $lt / $eq / $gt when you only need true/false.

One line: $cmp answers “is the left value less, equal, or greater?”—as -1, 0, or 1.

Frequently Asked Questions

$cmp compares two values and returns -1 if the first is less, 0 if they are equal, or 1 if the first is greater. Use it inside aggregation expression stages such as $project and $addFields.
The syntax is { $cmp: [ <expression1>, <expression2> ] }. Both sides can be fields, literals, or nested expressions.
Use $gt, $lt, $eq, and friends for true/false checks. Use $cmp when you need a three-way result (-1, 0, 1) for branching with $switch or custom comparison logic.
Yes. $cmp compares value and type using MongoDB’s BSON comparison order. For example, null sorts before numbers, so $cmp([null, 5]) returns -1.
A missing field is treated like null for comparison. $cmp(["$missing", 250]) returns -1 because null is less than a number.
Yes in spirit. Think of it as aggregation’s three-way compare: less → -1, equal → 0, greater → 1.

Next: $comment

Add comments to queries so logs and profilers are easier to read.

$comment 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