πŸƒDBQuestpractice MongoDB queries
0 / 110

MongoDB $unwind and array pipelines

Flattening arrays so you can group across their elements.  Β·  8 practice questions  Β·  Cheat sheet ↓

$unwind turns one document with an array of n elements into n documents, each holding a single element in place of the array. That is the step that makes array contents groupable: unwind grades, then $group on "$grades.grade" to count A grades per cuisine. A $unwind example in full form, { $unwind: { path: "$grades", preserveNullAndEmptyArrays: true } }, keeps documents whose array is missing or empty, which the short form silently drops.

The pipelines here follow the classic shape: $match to narrow, $unwind to flatten, $group to aggregate, $sort to rank. $sortByCount collapses the group-and-sort pair into one stage. Watch document counts as you go: unwinding a large array on a large collection multiplies the work, so match first and project away fields you will not need.

MongoDB $unwind practice questions

  1. Flatten the grades array and count how many grades of each letter (A, B, C) exist across all restaurants. Output the letter as _id and the count as count. easy restaurants
  2. Count how many A grades each cuisine has earned, as aGrades, sorted descending then by cuisine ascending. medium restaurants
  3. Across all orders, compute the total quantity sold per sku as unitsSold, sorted by sku ascending. medium orders
  4. Which genres appear most often? Flatten genres and use $sortByCount. medium movies
  5. How many inspections happened in each calendar month? Unwind grades and group by the month number of grades.date as _id, count as inspections, sorted by month. hard restaurants
  6. Unwind grades for Bombay Spice House and include the array position as a field called gradeIdx. Output name, gradeIdx and grades.grade only, no _id. hard restaurants
  7. Which 3 actors appear in the most movies? Unwind cast, count per actor as films, sort descending then by name ascending, and take the top 3. hard movies
  8. Find the average grade score per borough as avgScore, sorted ascending (best inspection scores first – lower is better). hard restaurants

Each question is answered in a live mongo-shell editor on this page; the result is checked against a reference solution.

$unwind and $sortByCount cheat sheet

One document per array element

{ $unwind: "$grades" }

A restaurant with 3 grades becomes 3 documents, each with grades as a single

object instead of an array. Everything else is copied.

The full form

{ $unwind: {
    path: "$grades",
    includeArrayIndex: "gradeIdx",       // adds 0,1,2...
    preserveNullAndEmptyArrays: true     // keep docs with [] or missing
} }

By default, documents with an empty or missing array are dropped.

That silently loses rows – reach for preserveNullAndEmptyArrays when counting.

The classic combo

db.restaurants.aggregate([
  { $unwind: "$grades" },
  { $match:  { "grades.grade": "A" } },
  { $group:  { _id: "$cuisine", aGrades: { $sum: 1 } } },
  { $sort:   { aGrades: -1 } }
])

unwind β†’ match β†’ group β†’ sort. Most "count things inside arrays" questions are

this exact shape.

$sortByCount is unwind's best friend

{ $unwind: "$genres" },
{ $sortByCount: "$genres" }   // == $group _id + $sum:1, then $sort desc

Gotchas

  • $match before $unwind filters documents; after $unwind it

filters individual elements. Both are useful – know which you meant.

  • Unwinding two arrays multiplies rows (a cartesian product). Rarely intended.

Common questions

What does $unwind do in MongoDB?

It outputs one document per array element: a restaurant with three grades becomes three documents, each with grades set to a single grade object. Everything else is copied. After that you can $match, $group or $sort on the element's fields.

Why do documents disappear after $unwind?

By default $unwind drops documents where the array is missing, null or empty. Pass the full form with preserveNullAndEmptyArrays: true to keep them, with the field absent or null in the output document.

How do I count values inside arrays across a collection?

Unwind, then group: [{ $unwind: "$grades" }, { $group: { _id: "$grades.grade", n: { $sum: 1 } } }]. { $sortByCount: "$grades.grade" } after the unwind does the count and the descending sort in one stage.

Continue:← Grouping & AccumulatorsJoins & Advanced Stages β†’

MongoDB topics:Finding & ProjectionComparison OperatorsLogical OperatorsElement & TypePattern MatchingSort, Limit & SkipArray QueriesEmbedded DocumentsAggregation BasicsGrouping & AccumulatorsJoins & Advanced StagesFull cheat sheet