$substrBytes is a MongoDB aggregation expression that returns a substring by UTF-8 byte index and byte count. For ASCII text, bytes match characters. For accents and emoji, one character can use 2–4 bytes—slices must land on character boundaries or the pipeline errors.
for each document:
s = evaluate(string)
i = evaluate(byteIndex)
n = evaluate(byteCount)
if s is null or missing:
result = ""
else if i or n is negative, or cut is mid-character:
error
else:
result = utf8Bytes(s) from i for n bytes
emit { ..., field: result }
Reference
Cheat Sheet
Keep these facts handy while slicing by bytes.
Topic
Detail
Type
Aggregation expression (not a find filter)
Syntax
{ $substrBytes: [ <string>, <index>, <count> ] }
Units
UTF-8 bytes (1–4 per character)
Null / missing
Returns ""
Rest of string
$substrBytes([s, i, { $subtract: [ { $strLenBytes: s }, i ] } ])
vs $substrCP
Bytes vs Unicode code points
Sample check
$substrBytes(["13Q1", 0, 2]) → "13"
Try it
Live Preview
Watch $substrBytes cut ASCII text by byte offsets. (For multi-byte text, stay on character boundaries.)
Simulates $substrBytes on ASCII (same idea as the mongosh examples below).
We store one inventory item with quarter code 13Q1. First we extract the year by bytes, then the rest using $strLenBytes. Run these in mongosh after inserting the sample data once.
Example 1 — Sample Data
Imagine one product with item code ABC1 and quarter 13Q1. We save it in a collection named inventory.
Check these before using $substrBytes in production pipelines.
UTF-8
Mid-character slices error
Start or end inside a multi-byte character fails the pipeline. Prefer $substrCP for character thinking.
count
No negative length shortcut
Unlike legacy $substr with -1, byte count must be ≥ 0. Use $strLenBytes − index for the remainder.
null
Null becomes empty string
Null or missing string input returns "", not an error. Non-string values still fail.
ASCII
ASCII looks like characters
For A–Z codes and digits, bytes equal characters. The difference appears with accents and emoji.
Analysis
Performance Notes
Approach
Cost
Best for
$substrBytes alone
Per-document byte slice
Fixed ASCII prefixes
+ $strLenBytes
Length + slice
Dynamic “rest of string”
Store split fields
No runtime slice
Hot filters on year / prefix
Byte slicing is cheap for short strings. Filter early with $match when only some documents need a prefix extracted.
Remember
Key Takeaways
Role: substring by UTF-8 byte index + count.
Boundaries: never cut mid-character.
Rest: use $strLenBytes − start (not length -1).
Characters: use $substrCP instead.
One line:$substrBytes answers “which UTF-8 bytes do I get from this start for this count?”—on valid character boundaries only.
Frequently Asked Questions
$substrBytes returns part of a string starting at a zero-based UTF-8 byte index for a given byte count. For ASCII text, byte positions match character positions. Use it inside aggregation expression stages such as $project and $addFields.
Use { $substrBytes: [ <string>, <byte index>, <byte count> ] }. Both index and count must resolve to non-negative integers. Slices must land on valid UTF-8 character boundaries.
$substrBytes uses byte offsets (storage-oriented). $substrCP uses Unicode code-point offsets (character-oriented). For accents and emoji, prefer $substrCP for user-facing slices.
MongoDB errors. The start index or end of the range cannot land in the middle of a UTF-8 character. Use $substrCP when you think in characters, not bytes.
If the string is null or the field is missing, $substrBytes returns an empty string "". Non-string values cause an error.
Unlike legacy $substr with length -1, $substrBytes needs a non-negative count. Compute remaining bytes with $subtract and $strLenBytes, or use $substrCP if you want character-based slicing.