MongoDB $substrBytes Operator

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

What You’ll Learn

The $substrBytes operator extracts part of a string using byte offsets in UTF-8 encoding. Use it when storage size, index limits, or wire-protocol byte constraints matter more than visible character count.

01

Byte Slice

UTF-8 positions.

02

Syntax

[ str, start, len ].

03

Zero-Based

Byte index 0.

04

$project Stage

Truncated fields.

05

Use Cases

Storage, indexes.

06

vs $substrCP

Bytes vs chars.

Definition and Usage

In MongoDB’s aggregation framework, the $substrBytes operator returns a substring starting at a zero-based byte index for a given byte length. For example, on ASCII text { $substrBytes: [ "hello", 0, 3 ] } returns "hel" (3 bytes = 3 characters).

This is the modern replacement for the legacy $substr operator. Pair it with $strLenBytes when you need to truncate text to a maximum storage size, or use $substrCP when slicing by visible characters instead.

💡
Beginner Tip

For plain English ASCII, byte slicing behaves like character slicing. With accents, CJK text, or emoji, byte counts differ from character counts — slice carefully or use $substrCP.

📝 Syntax

The $substrBytes operator takes a string, byte start index, and byte length:

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

Literal Examples

mongosh
{ $substrBytes: [ "hello", 0, 3 ] }
// Result: "hel"  (3 bytes)

{ $substrBytes: [ "hello", 1, 3 ] }
// Result: "ell"  (skip 1 byte, take 3)

{ $substrBytes: [ "$text", 0, 100 ] }
// First 100 bytes of the text field

Syntax Rules

  • First argument — string expression (field path or literal).
  • Second argument — zero-based byte start index (integer).
  • Third argument — number of bytes to extract.
  • Use inside $project, $addFields, or $set.
  • Start beyond string byte length — returns "".
  • Avoid splitting mid-character in UTF-8 unless you understand the byte layout.
  • null string — returns null.

💡 $substrBytes vs $substrCP vs $substr

$substrBytes — start and length in UTF-8 bytes (storage-oriented)
$substrCP — start and length in Unicode code points (character-oriented)
$substr — legacy alias; use explicit byte or CP operators instead
Example: slicing "Hi 👋" at byte 3 differs from slicing at code point 3.

⚡ Quick Reference

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

Byte truncation

Skip bytes
{
  $substrBytes: ["$log", 8, 20]
}

From byte 8

ASCII
{
  $substrBytes: ["Mongo", 0, 3]
}

Returns "Mon"

Pair with
$strLenBytes

Measure first

Examples Gallery

Slice strings by byte offset on ASCII and UTF-8 text, truncate to storage limits, and compare with code-point slicing.

📚 Basic Byte Slicing

Start with a logs collection and extract substrings by byte position.

Sample Input Documents

Suppose you have a logs collection with message text:

mongosh
[
  { "_id": 1, "message": "INFO: Server started" },
  { "_id": 2, "message": "ERROR: Connection failed" },
  { "_id": 3, "message": "café au lait" },
  { "_id": 4, "message": "Hi 👋 MongoDB" }
]

Example 1 — Basic $substrBytes on ASCII Text

Skip the six-byte "INFO: " prefix and take the next 20 bytes:

mongosh
db.logs.aggregate([
  {
    $project: {
      message: 1,
      payload: {
        $substrBytes: [ "$message", 6, 20 ]
      }
    }
  }
])

How It Works

Start at byte index 6 to skip "INFO: " or "ERROR:" prefixes (adjust per format). Length limits how many bytes are returned.

📈 Truncation and Comparison

Enforce byte budgets and compare byte-based vs character-based slicing.

Example 2 — Truncate to a Maximum Byte Size

Keep only the first 100 bytes of a long message field:

mongosh
db.logs.aggregate([
  {
    $project: {
      message: 1,
      preview: {
        $substrBytes: [ "$message", 0, 100 ]
      },
      byteLength: {
        $strLenBytes: "$message"
      }
    }
  }
])

How It Works

Useful when an index key, API payload, or column has a fixed byte budget. Pair with $strLenBytes to see whether truncation occurred.

Example 3 — UTF-8 Byte Layout

On "café", the accented é uses 2 bytes in UTF-8:

mongosh
db.logs.aggregate([
  {
    $project: {
      message: 1,
      first3Bytes: {
        $substrBytes: [ "$message", 0, 3 ]
      },
      bytes: { $strLenBytes: "$message" },
      chars: { $strLenCP: "$message" }
    }
  }
])

// "café" → first3Bytes: "caf" (stops before full é)
// bytes: 5, chars: 4

How It Works

Byte slicing can cut inside a multi-byte character. For user-visible truncation, prefer $substrCP instead.

Example 4 — $substrBytes vs $substrCP on Emoji

Compare byte-based and code-point slicing on the same string:

mongosh
db.logs.aggregate([
  {
    $project: {
      message: 1,
      byBytes: {
        $substrBytes: [ "$message", 0, 4 ]
      },
      byCodePoints: {
        $substrCP: [ "$message", 0, 4 ]
      }
    }
  }
])

// "Hi 👋 MongoDB"
// byBytes:      first 4 bytes  → "Hi �" (may split emoji)
// byCodePoints: first 4 chars  → "Hi 👋"

How It Works

Four bytes may not equal four visible characters when emoji or non-ASCII text is present. Choose the operator that matches your requirement.

Bonus — Slice From the End Using Byte Length

Extract the last 4 bytes (ASCII digits only in this example):

mongosh
db.orders.aggregate([
  {
    $project: {
      orderId: 1,
      suffix: {
        $substrBytes: [
          "$orderId",
          { $subtract: [ { $strLenBytes: "$orderId" }, 4 ] },
          4
        ]
      }
    }
  }
])

// "ORD-12345678" → suffix: "5678"

How It Works

Subtract the desired byte count from total byte length to compute the start index. Works cleanly for fixed-width ASCII suffixes.

🚀 Use Cases

  • Storage truncation — cap string fields to a maximum byte size before indexing or export.
  • Index key limits — preview or trim values approaching MongoDB index key byte limits.
  • Log parsing — skip fixed-width ASCII headers in log lines by byte offset.
  • Legacy compatibility — explicit replacement for the deprecated $substr operator.

🧠 How $substrBytes Works

1

MongoDB reads the string

The string is interpreted as BSON UTF-8 bytes from a field path or literal.

Input
2

Byte start index is applied

MongoDB moves to the zero-based byte position. If start is past the end, the result is empty.

Position
3

Byte length is extracted

Up to length bytes are copied into the result substring.

Extract
=

Byte substring returned

Use for storage limits; switch to $substrCP for character-safe slices.

Conclusion

The $substrBytes operator extracts substrings using UTF-8 byte offsets and lengths. It is the right tool for storage-oriented truncation, log parsing on ASCII, and replacing legacy $substr in modern pipelines.

For user-facing character slicing with emoji and international text, use $substrCP. Next in the series: $substrCP.

💡 Best Practices

✅ Do

  • Use $substrBytes for byte-budget truncation and index sizing
  • Pair with $strLenBytes to measure before and after slicing
  • Prefer $substrCP for user-visible character limits
  • Test ASCII and UTF-8 samples separately
  • Guard null fields with $ifNull before slicing

❌ Don’t

  • Slice multi-byte UTF-8 text at arbitrary byte positions without testing
  • Use byte slicing for tweet-style character counters
  • Confuse $substrBytes with $slice (arrays vs strings)
  • Assume byte length equals character count for all languages
  • Use negative start indices — they are not supported

Key Takeaways

Knowledge Unlocked

Five things to remember about $substrBytes

Use these points when slicing strings by bytes in MongoDB.

5
Core concepts
📝 02

[ s, start, len ]

Bytes, not chars.

Syntax
📊 03

Storage limits

Index & size.

Use case
🛠 04

+ $strLenBytes

Measure first.

Pattern
05

vs $substrCP

Char-safe slice.

Compare

❓ Frequently Asked Questions

$substrBytes returns part of a string starting at a zero-based byte offset for a given byte length. Positions are measured in UTF-8 bytes, not visible characters. For ASCII text, byte positions match character positions.
The syntax is { $substrBytes: [ <string>, <start>, <length> ] }. Start is the zero-based byte index; length is how many bytes to include.
$substrBytes uses byte offsets (storage-oriented). $substrCP uses Unicode code-point offsets (character-oriented). For emoji and international text, $substrCP is safer for user-facing slices.
If start or length falls in the middle of a UTF-8 character, MongoDB may return unexpected results or invalid sequences. Always slice at valid byte boundaries, or use $substrCP for character-safe extraction.
If the string expression is null, $substrBytes returns null. Use $ifNull to default to an empty string when the field may be missing.

Continue the Operator Series

Move on to $substrCP for code-point substring extraction, or review $strLenBytes for byte-length measurement.

Next: $substrCP →

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