$range is a MongoDB aggregation expression that builds an array of integers from a start value (inclusive) to an end value (exclusive), with an optional step. Think of it as a number-sequence generator.
Add a non-zero step for every Nth value or counting down.
Optionally $unwind the array to get one document per number.
Piece
Required?
Role
start
Yes
First integer (inclusive)
end
Yes
Stop before this integer
step
No
Increment (default 1; ≠ 0)
Pseudocode
Pseudocode
start, end, step = evaluate(args) // step defaults to 1
result = []
i = start
if step > 0:
while i < end:
result.push(i)
i = i + step
else if step < 0:
while i > end:
result.push(i)
i = i + step
else:
error // step cannot be 0
emit { ..., field: result }
Reference
Cheat Sheet
Keep these facts handy while building number sequences.
Topic
Detail
Type
Aggregation expression (returns an array)
Syntax
{ $range: [start, end, step?] }
Bounds
Start in · end out
Default step
1
Empty result
No integers fit → []
Downward
Negative step
Sample
[0, 5] → [0, 1, 2, 3, 4]
Try it
Live Preview
Pick a start, end, and step to see the array $range would build.
A small room needs seat labels 1 through 5. Because end is exclusive, we call $range with [1, 6].
Calculation
Want seats: 1, 2, 3, 4, 5
$range: [1, 6]
start = 1 → include
next = 2, 3, 4, 5
end = 6 → stop (not included)
result → [1, 2, 3, 4, 5]
If you wrote [1, 5] by mistake:
→ [1, 2, 3, 4] // missing seat 5
Code
MongoDB Examples
We use one room document. First insert it, then build seat numbers with $range, then show a stepped sequence. Run these in mongosh after inserting the sample data once.
Example 1 — Sample Data
Imagine one classroom room named A1 that needs five seats. We save it in a collection named rooms.
Stop before 10. End is exclusive, so 10 is not in the array.
Edge Cases & Pitfalls
Check these before generating large sequences in production.
end
End is exclusive
Want 1…N? Use [1, N + 1]. Writing [1, N] drops N.
step
Step cannot be 0
A zero step is invalid and errors. Use a positive or negative non-zero step.
empty
Empty arrays are normal
If no integers fit (for example [5, 5] or [5, 0] with step 1), the result is [].
size
Huge ranges cost memory
Very large sequences create large arrays. Keep ranges small, or unwind only what you need.
Analysis
Performance Notes
Approach
Cost
Best for
Small $range
Cheap array build
Indexes, seat lists
$range + $unwind
1 doc → many docs
Per-slot processing
Huge end − start
Large memory
Avoid / chunk instead
Building a short sequence is inexpensive. Cost grows with array length and with $unwind, which multiplies documents.
Remember
Key Takeaways
Role: build an integer sequence array.
Bounds: start inclusive, end exclusive.
Step: default 1; use negatives to count down.
Sample:[1, 6] → seats [1, 2, 3, 4, 5].
One line:$range answers “give me integers from start up to (but not including) end.”
Frequently Asked Questions
$range builds an array of integers from a start value (inclusive) up to an end value (exclusive), with an optional step. For example, { $range: [0, 5] } returns [0, 1, 2, 3, 4].
Use { $range: [ <start>, <end> ] } or { $range: [ <start>, <end>, <step> ] }. Start is inclusive, end is exclusive, and step defaults to 1. Step cannot be 0.
No. End is exclusive. { $range: [0, 5] } stops before 5. To include 5, use end 6.
Yes. Use a negative step when start is greater than end. Example: { $range: [5, 0, -1] } returns [5, 4, 3, 2, 1].
Create the sequence with $addFields or $project, then $unwind the array to get one document per number. Useful for indexes, seat slots, or repeated rows.
You get an empty array []. For example, { $range: [5, 5] } or { $range: [5, 0] } with the default positive step returns [].