$substr is a MongoDB aggregation expression that returns a substring starting at a zero-based index for a given length. It is deprecated since 3.4 and is an alias for $substrBytes. Prefer $substrBytes or $substrCP in new code.
Set length, or use -1 to take everything from start to the end.
Piece
Required?
Role
String
Yes
Source text (field or literal)
Start
Yes
Zero-based index (negative → "")
Length
Yes
How many units to take (-1 = rest of string)
Pseudocode
Pseudocode
for each document:
s = evaluate(string)
start = evaluate(startIndex)
len = evaluate(length)
if start < 0:
result = ""
else if len < 0:
result = s from start to end
else:
result = s from start for len units
emit { ..., field: result }
Reference
Cheat Sheet
Keep these facts handy while extracting substrings.
Topic
Detail
Type
Aggregation expression (not a find filter)
Syntax
{ $substr: [ <string>, <start>, <length> ] }
Status
Deprecated alias of $substrBytes (since 3.4)
Negative start
Returns ""
Negative length
From start to end of string
Unicode
Prefer $substrCP for character-safe cuts
Sample check
$substr(["13Q1", 0, 2]) → "13"
Try it
Live Preview
Watch $substr cut a quarter code into year and quarter parts. Try the rest-of-string pattern with length -1.
Simulates $substr on ASCII text (same idea as the mongosh examples below).
We store one inventory item with quarter code 13Q1. First we extract the year, then the rest of the string. 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.
Same stored document. Still using "13Q1" from Example 1.
Year again. Indices 0..2 → "13".
Rest of string. Start at 2 with length -1 → "Q1".
Easy check. Putting year and qtr back together rebuilds "13Q1".
Edge Cases & Pitfalls
Check these before using $substr in production pipelines.
deprecated
Prefer $substrBytes / $substrCP
$substr is a legacy alias. New code should call $substrBytes or $substrCP explicitly.
Unicode
Byte cuts can break characters
Because $substr aliases $substrBytes, slicing in the middle of a multi-byte character can error. Use $substrCP for character-safe cuts.
negative
Negative start vs negative length
Negative start → "". Negative length → take from start to the end of the string.
ASCII
Best for ASCII codes
Quarter codes, SKUs, and other ASCII prefixes are a natural fit. International text needs $substrCP.
Analysis
Performance Notes
Approach
Cost
Best for
$substr alone
Per-document string slice
Fixed ASCII prefixes / suffixes
Two slices (year + rest)
Still O(docs)
Splitting packed codes
Store split fields
No runtime slice
Hot filters on year / quarter
Substring extraction is cheap for short strings. If you filter on year often, store year as its own field. Filter early with $match when only some documents need slicing.
Remember
Key Takeaways
Role: extract a piece of a string by start + length.
Legacy: alias of $substrBytes (prefer the modern name).
Rest of string: use length -1.
Unicode: use $substrCP for character-safe cuts.
One line:$substr answers “what piece of this string do I get from this start for this length?”—as a legacy alias of $substrBytes.
Frequently Asked Questions
$substr returns part of a string starting at a zero-based index for a given length. For example, { $substr: [ "hello", 0, 2 ] } returns "he". Use it inside aggregation expression stages such as $project and $addFields.
Use { $substr: [ <string>, <start>, <length> ] }. Start is the zero-based index where extraction begins; length is how many units to include (or -1 for the rest of the string).
$substr is deprecated since MongoDB 3.4 and is an alias for $substrBytes (byte-based positions). Prefer $substrBytes or $substrCP (code-point positions) in new code. Prefer $substrCP for Unicode character slicing.
A negative start returns an empty string "". A negative length means “from start to the end of the string.”
As an alias of $substrBytes, null or a missing string field yields an empty string "". Prefer $ifNull when you want an explicit default.
Use $substrCP when you need character-safe slicing for accents and emoji. $substr / $substrBytes count bytes and can break multi-byte UTF-8 characters.