Array expressions ($size, $arrayElemAt, $filter) in MongoDB - Time & Space Complexity
When working with arrays in MongoDB, it's important to know how the time to process them grows as the array gets bigger.
We want to understand how operations like counting elements, picking one element, or filtering affect performance as the array size increases.
Analyze the time complexity of the following code snippet.
db.collection.aggregate([
{
$project: {
totalItems: { $size: "$items" },
firstItem: { $arrayElemAt: ["$items", 0] },
filteredItems: { $filter: {
input: "$items",
as: "item",
cond: { $gt: ["$$item.price", 100] }
}}
}
}
])
This code counts the number of items, gets the first item, and filters items with price over 100 in each document.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Traversing the array to filter items.
- How many times: The filter checks each element once, so it runs once per item in the array.
Explain the growth pattern intuitively.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 checks for filtering, plus 1 for size and 1 for first element |
| 100 | About 100 checks for filtering, plus 1 for size and 1 for first element |
| 1000 | About 1000 checks for filtering, plus 1 for size and 1 for first element |
Pattern observation: The filtering work grows directly with the number of items, while size and first element are quick constant-time operations.
Time Complexity: O(n)
This means the time to run this aggregation grows linearly with the number of items in the array.
[X] Wrong: "Getting the size or first element of an array takes as long as filtering all items."
[OK] Correct: Counting elements or picking one element is very fast and does not depend on array size, unlike filtering which checks each item.
Understanding how array operations scale helps you write efficient queries and explain your choices clearly in interviews.
"What if we changed the filter condition to check nested arrays inside each item? How would the time complexity change?"
Practice
$size do when used on an array field?Solution
Step 1: Understand the purpose of
The$size$sizeoperator counts the number of elements inside an array.Step 2: Compare with other operators
$arrayElemAtpicks an element by position,$filterselects elements by condition, and sorting is unrelated.Final Answer:
Counts how many elements are in the array -> Option AQuick Check:
$size= count elements [OK]
- Confusing $size with $arrayElemAt
- Thinking $size filters elements
- Assuming $size sorts arrays
items using MongoDB aggregation?Solution
Step 1: Recall zero-based indexing in $arrayElemAt
The third element is at index 2 because counting starts at 0.Step 2: Check syntax correctness
The correct syntax uses$arrayElemAtwith the array field prefixed by$and the zero-based index.Final Answer:
{ $arrayElemAt: ["$items", 2] } -> Option CQuick Check:
Third element index = 2 [OK]
- Using 1-based index instead of 0-based
- Missing $ before field name
- Confusing $size with $arrayElemAt
{ scores: [10, 20, 30, 40] }, what will the aggregation expression { $size: "$scores" } return?Solution
Step 1: Understand what
$sizedoes$sizecounts the number of elements in the array.Step 2: Count elements in the array
The array[10, 20, 30, 40]has 4 elements.Final Answer:
4 -> Option AQuick Check:
Array length = 4 [OK]
- Returning the third element instead of count
- Returning the whole array instead of count
- Assuming syntax error
{ $arrayElemAt: ["$values", "1"] }Solution
Step 1: Check the type of index in $arrayElemAt
The index must be a number, but here it is a string "1".Step 2: Confirm correct field referencing
The field name "$values" is correctly prefixed with$.Final Answer:
Index must be a number, not a string -> Option BQuick Check:
Index type = number, not string [OK]
- Using string instead of number for index
- Omitting $ before field name
- Thinking array must be wrapped differently
tags as an array of strings. How would you write a MongoDB aggregation expression to get the count of tags that start with the letter 'a'?Solution
Step 1: Use $filter to select tags starting with 'a'
The$filteroperator creates a new array with tags matching the regex /^a/.Step 2: Use $size to count filtered tags
$sizecounts how many tags matched the condition.Final Answer:
{ $size: { $filter: { input: "$tags", as: "tag", cond: { $regexMatch: { input: "$$tag", regex: /^a/ } } } } } -> Option DQuick Check:
Filter then count = correct approach [OK]
- Using $arrayElemAt instead of $filter
- Filtering with exact match instead of regex
- Counting whole array without filtering
Ready to prove it?
Pass the test and this pattern moves unknown
