MongoDB $substrCP Operator

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

What Is $substrCP?

$substrCP is a MongoDB aggregation expression that returns a substring by Unicode code-point index and count. Accents and most emoji count as one unit each, so it is the safe choice for display truncation. For byte budgets, use $substrBytes.

Remember
$substrCP = substring by Unicode code points

{ $substrCP: [ <string>, <cpIndex>, <cpCount> ] }

"café" + 0, 3 → "caf"
"café" + 3, 1 → "é"
"cafétéria" + 0, 5 → "cafét"

null / missing string → ""
need bytes? → use $substrBytes
legacy $substr → alias of $substrBytes (not CP)
UsePrefer
Character / display slice$substrCP
Byte / storage slice$substrBytes
Measure characters first$strLenCP
Legacy name$substr (bytes, not code points)

How to Use $substrCP in MongoDB

Pass the string, a non-negative code-point start, and a non-negative code-point count.

  1. Choose an expression stage ($addFields or $project).
  2. Pass the string expression as the first argument.
  3. Set code-point index and count (both ≥ 0).
  4. For “rest of string,” compute remaining code points with $strLenCP and $subtract.
PieceRequired?Role
StringYesSource text (field or literal)
Code-point indexYesZero-based character start (≥ 0)
Code-point countYesHow many characters to take (≥ 0)

Pseudocode

Pseudocode
for each document:
    s = evaluate(string)
    i = evaluate(codePointIndex)
    n = evaluate(codePointCount)
    if s is null or missing:
        result = ""
    else if i or n is negative:
        error
    else:
        result = codePoints(s) from i for n characters
    emit { ..., field: result }

Cheat Sheet

Keep these facts handy while slicing by code points.

TopicDetail
TypeAggregation expression (not a find filter)
Syntax{ $substrCP: [ <string>, <index>, <count> ] }
UnitsUnicode code points (characters)
Null / missingReturns ""
Rest of string$substrCP([s, i, { $subtract: [ { $strLenCP: s }, i ] } ])
vs $substrBytesCharacters vs UTF-8 bytes
Sample check$substrCP(["café", 0, 3]) → "caf"

Live Preview

Watch $substrCP cut by characters. Try ASCII and accented text where one letter can still be one code point.

Simulates $substrCP (same idea as the mongosh examples below).

Result
string = "café"
index  = 0
count  = 3

$substrCP → "caf"

{ preview: "caf" }

Worked Walkthrough — café

The word café has 4 code points. We take a 3-character preview, then the remaining letter é.

Calculation
String: "café"
Index:   0 1 2 3
Chars:   c a f é

Preview (3 code points from 0):
  $substrCP(["$title", 0, 3]) → "caf"

Rest (length − 3 from index 3):
  len = $strLenCP("$title") → 4
  count = 4 − 3 → 1
  $substrCP(["$title", 3, 1]) → "é"

Check: "caf" + "é" = "café" ✓
Note: $substrBytes mid-slice can error; $substrCP stays character-safe

MongoDB Examples

We store one title café. First we extract a character preview, then the rest using $strLenCP. Run these in mongosh after inserting the sample data once.

Example 1 — Sample Data

Imagine one post with title café. We save it in a collection named posts.

mongosh
db.posts.insertOne({
  _id: 1,
  title: "café"
});

How the Data Is Stored in MongoDB

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

mongosh
db.posts.find()

Read that document like this:

Field in MongoDBValuePlain English
_id1Document id for this lesson
title"café"4 code points; é is still one character
Picture
title code points: c a f é
index:             0 1 2 3

indexes 0–2 → "caf"   preview
index 3     → "é"     rest

How It Works

  1. Insert once. insertOne adds a single post document.
  2. Accent stays one character. é is one code point even if it uses two UTF-8 bytes.
  3. find() shows the same shape. What you inserted is what you get back—ready for $substrCP next.

Example 2 — Character Preview

Goal: take the first three code points of title as a short preview ("caf").

mongosh
db.posts.aggregate([
  {
    $addFields: {
      preview: {
        $substrCP: ["$title", 0, 3]
      }
    }
  }
]);

How It Works

  1. Read the stored string. MongoDB already has title: "café" from Example 1.
  2. Start at code point 0. Extraction begins at the first character.
  3. Take 3 code points. That yields "caf".
  4. Keep all fields. $addFields adds preview next to the original title.

Example 3 — Extract the Rest of the String

Same document: start at code point 3 and take the remaining characters using $strLenCP minus 3.

mongosh
db.posts.aggregate([
  {
    $addFields: {
      preview: { $substrCP: ["$title", 0, 3] },
      rest: {
        $substrCP: [
          "$title",
          3,
          { $subtract: [{ $strLenCP: "$title" }, 3] }
        ]
      }
    }
  }
]);

How It Works

  1. Same stored document. Still using "café" from Example 1.
  2. Measure characters. $strLenCP returns 4.
  3. Remaining count. $subtract does 4 − 3 = 1.
  4. Slice from index 3. One code point yields "é"—kept whole, not split mid-byte.

Edge Cases & Pitfalls

Check these before using $substrCP in production pipelines.

vs bytes

Not the same as $substrBytes

$substrBytes can error on mid-character cuts. $substrCP thinks in characters and is safer for UI previews.

count

Index and count must be ≥ 0

There is no negative-length shortcut. Use $strLenCP − index for the remainder.

null

Null becomes empty string

Null or missing string input returns "", not an error. Non-string values still fail.

grapheme

Code points ≠ grapheme clusters

Some emoji or combined marks are multiple code points. $substrCP counts code points, not always what a user perceives as one glyph.

Performance Notes

ApproachCostBest for
$substrCP alonePer-document Unicode slicePreviews, display truncation
+ $strLenCPLength + sliceDynamic “rest of string”
$substrBytesSimilar cost, different unitsStorage / byte budgets

Character slicing is cheap for short titles. Filter early with $match when only some documents need a preview.

Key Takeaways

  • Role: substring by Unicode code-point index + count.
  • Use when: display / character-safe truncation.
  • Rest: use $strLenCP − start.
  • Bytes: use $substrBytes instead.

One line: $substrCP answers “which characters do I get from this start for this count?”—without cutting accents or emoji mid-byte.

Frequently Asked Questions

$substrCP returns part of a string starting at a zero-based Unicode code-point index for a given code-point count. Code points correspond to characters, so accents and most emoji count as one unit each. Use it inside aggregation expression stages such as $project and $addFields.
Use { $substrCP: [ <string>, <code point index>, <code point count> ] }. Both index and count must resolve to non-negative integers.
$substrCP slices by Unicode code points (characters). $substrBytes slices by UTF-8 storage bytes. Prefer $substrCP for display truncation; prefer $substrBytes for storage or byte budgets.
Prefer $substrCP whenever character boundaries matter—accents, emoji, or international text. Legacy $substr is an alias of $substrBytes and can break multi-byte characters.
If the string is null or the field is missing, $substrCP returns an empty string "". Non-string values cause an error.
Compute remaining code points with $subtract and $strLenCP, then pass that count to $substrCP. Index and count must stay non-negative.

Next: $subtract

Subtract numbers or dates in an aggregation pipeline.

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