MongoDB $substrCP Operator

Beginner
⏱️ 8 min read
📚 Updated: Jul 2026
🎯 4 Examples
String Operations

What You’ll Learn

The $substrCP operator extracts part of a string using Unicode code-point positions. It is the recommended way to slice text when emoji, accents, and international characters must count as single characters.

01

Code-Point Slice

Character-safe.

02

Syntax

[ str, start, len ].

03

Emoji Safe

1 emoji = 1 unit.

04

$project Stage

Preview fields.

05

Use Cases

Limits, previews.

06

vs $substrBytes

Chars vs bytes.

Definition and Usage

In MongoDB’s aggregation framework, the $substrCP operator returns a substring starting at a zero-based code-point index for a given code-point length. CP stands for code points — the Unicode units that roughly match visible characters. For example, { $substrCP: [ "hello", 0, 3 ] } returns "hel".

Use $substrCP for tweet-style character limits, title previews, and any user-facing truncation. Use $substrBytes when you need storage-byte positions instead. Pair with $strLenCP to measure length before slicing.

💡
Beginner Tip

On "Hi 👋", { $substrCP: [ "Hi 👋", 0, 4 ] } returns the full string (4 code points). Byte-based slicing might break the emoji in the middle.

📝 Syntax

The $substrCP operator takes a string, code-point start index, and code-point length:

mongosh
{ $substrCP: [ <string>, <start>, <length> ] }

Literal Examples

mongosh
{ $substrCP: [ "hello world", 0, 5 ] }
// Result: "hello"

{ $substrCP: [ "hello world", 6, 5 ] }
// Result: "world"

{ $substrCP: [ "Hi 👋", 0, 4 ] }
// Result: "Hi 👋"  (emoji counts as 1 code point)

Syntax Rules

  • First argument — string expression (field path or literal).
  • Second argument — zero-based code-point start index (integer).
  • Third argument — number of code points to extract.
  • Use inside $project, $addFields, or $set.
  • Start beyond string length — returns "".
  • null string — returns null.

💡 $substrCP vs $substrBytes vs $substr

$substrCP — start and length in code points (recommended for display)
$substrBytes — start and length in UTF-8 bytes (storage-oriented)
$substr — legacy alias; prefer explicit CP or Bytes operators
Use $substrCP + $strLenCP for character limits users understand.

⚡ Quick Reference

QuestionAnswer
Operator typeAggregation expression operator (string)
Syntax{ $substrCP: [ string, start, length ] }
Start indexZero-based code-point offset
LengthNumber of code points to include
Related operators$strLenCP, $substrBytes
Common stages$project, $addFields, $set
First 50 chars
{
  $substrCP: ["$body", 0, 50]
}

Display preview

Skip prefix
{
  $substrCP: ["$text", 3, 10]
}

From char 3

Emoji
{
  $substrCP: ["Hi 👋", 0, 4]
}

Full string

Pair with
$strLenCP

Count first

Examples Gallery

Slice strings by visible character count, truncate posts safely with emoji, and compare with byte-based extraction.

📚 Basic Code-Point Slicing

Start with a posts collection and extract character-based substrings.

Sample Input Documents

Suppose you have a posts collection with titles and body text:

mongosh
[
  { "_id": 1, "title": "Hello World", "body": "Short update today." },
  { "_id": 2, "title": "MongoDB 🚀", "body": "Learning aggregation pipelines!" },
  { "_id": 3, "title": "café culture", "body": "Unicode and emoji 👋 work fine." }
]

Example 1 — Basic $substrCP on a Field

Extract the first five characters of each title:

mongosh
db.posts.aggregate([
  {
    $project: {
      title: 1,
      titlePreview: {
        $substrCP: [ "$title", 0, 5 ]
      }
    }
  }
])

How It Works

Start at code-point index 0 and take 5 code points. Accented letters and spaces each count as one code point.

📈 Emoji, Previews, and Comparison

Handle Unicode safely and build user-facing truncated text.

Example 2 — Emoji-Safe Substring

Take the first four visible characters including emoji:

mongosh
db.posts.aggregate([
  {
    $project: {
      body: 1,
      snippet: {
        $substrCP: [ "$body", 0, 4 ]
      }
    }
  }
])

// "Unicode and emoji 👋 work fine."
// snippet: "Unic"  (4 code points)

// Compare: $substrBytes at byte 4 might split a multi-byte character

How It Works

$substrCP never splits a code point in half. That is why it is preferred over byte-based slicing for international text.

Example 3 — Truncate Body to 50 Characters

Create a display preview capped at 50 code points:

mongosh
db.posts.aggregate([
  {
    $project: {
      title: 1,
      bodyPreview: {
        $substrCP: [ "$body", 0, 50 ]
      },
      fullLength: {
        $strLenCP: "$body"
      }
    }
  }
])

How It Works

Pair $substrCP with $strLenCP to show both the preview and whether the original was longer than 50 characters.

Example 4 — $substrCP vs $substrBytes

See the difference on the same emoji string:

mongosh
db.posts.aggregate([
  {
    $project: {
      body: 1,
      byCodePoints: {
        $substrCP: [ "$body", 0, 20 ]
      },
      byBytes: {
        $substrBytes: [ "$body", 0, 20 ]
      }
    }
  }
])

// On text with emoji, byte slice may end mid-character
// Code-point slice always ends on character boundaries

How It Works

Twenty code points usually means twenty visible characters. Twenty bytes may be fewer characters and can corrupt emoji at the boundary.

Bonus — Last Four Characters

Extract the last four code points using $strLenCP:

mongosh
db.users.aggregate([
  {
    $project: {
      username: 1,
      suffix: {
        $substrCP: [
          "$username",
          { $subtract: [ { $strLenCP: "$username" }, 4 ] },
          4
        ]
      }
    }
  }
])

// "developer123" → suffix: "r123"

How It Works

Compute start as total code-point length minus 4, then slice 4 code points. Works correctly even when the username contains emoji or accented letters.

🚀 Use Cases

  • Display previews — show the first N characters of posts, comments, or descriptions in lists.
  • Character limits — enforce tweet-style or form-field max character counts.
  • International content — slice text with accents, CJK characters, and emoji without corruption.
  • Data cleanup — extract fixed segments from user-generated text for reporting.

🧠 How $substrCP Works

1

MongoDB reads the string

The expression resolves to a UTF-8 string from a field path or literal.

Input
2

Code-point start is applied

MongoDB moves to the zero-based code-point position. Each visible character (including most emoji) is one unit.

Position
3

Code points are extracted

Up to length complete code points are copied into the result.

Extract
=

Character-safe substring

Use in $project for previews, limits, and Unicode-aware parsing.

Conclusion

The $substrCP operator extracts substrings by Unicode code points, making it the best choice for user-facing character limits and previews. It handles emoji and international text correctly where byte-based operators may fail.

For storage-byte slicing, use $substrBytes instead. Next in the series: $subtract.

💡 Best Practices

✅ Do

  • Use $substrCP for display truncation and character limits
  • Pair with $strLenCP to measure length and compute suffix slices
  • Prefer $substrCP over legacy $substr for clarity
  • Test with emoji and accented characters, not just ASCII
  • Guard null fields with $ifNull before slicing

❌ Don’t

  • Use $substrCP for index key byte limits — use $substrBytes
  • Assume it matches JavaScript .length for all Unicode (surrogate pairs differ)
  • Confuse $substrCP with $slice (arrays vs strings)
  • Use negative start indices — they are not supported
  • Forget that start beyond length returns an empty string

Key Takeaways

Knowledge Unlocked

Five things to remember about $substrCP

Use these points when slicing strings in MongoDB.

5
Core concepts
📝 02

[ s, start, len ]

CP units.

Syntax
😀 03

Emoji safe

No mid-char cut.

Unicode
🛠 04

Previews

First N chars.

Use case
05

vs $substrBytes

Display vs storage.

Compare

❓ Frequently Asked Questions

$substrCP returns part of a string starting at a zero-based code-point index for a given code-point length. Code points correspond to visible characters, so one emoji usually counts as one unit. It is the recommended operator for Unicode-safe substring extraction.
The syntax is { $substrCP: [ <string>, <start>, <length> ] }. Start is the zero-based code-point index; length is how many code points to include.
$substrCP slices by Unicode code points (characters users see). $substrBytes slices by UTF-8 storage bytes. Use $substrCP for display truncation; use $substrBytes for storage or index byte limits.
Always prefer $substrCP over the legacy $substr operator when you care about correct character boundaries with emoji, accents, or international text. $substrCP is explicit and Unicode-aware.
If the string expression is null, $substrCP returns null. Use $ifNull to provide a default empty string when the field may be missing.

Continue the Operator Series

Move on to $subtract for numeric subtraction, or review $strLenCP for character counting.

Next: $subtract →

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.

5 people found this page helpful