The reference dashboard is hand-drawn SVG, which makes it portable but teaches you nothing about the tool this module is actually about. This page closes that gap. Every panel on that dashboard is backed by an aggregation pipeline, and every one of those pipelines maps onto an Atlas Charts chart. Run the query, read the shape, pick the encoding, repeat ten times — and you have the same dashboard, built the way you would build it at work.
A fair question, and worth answering before you spend ninety minutes on it. The dashboard on this site renders from a precomputed JSON file. That is a reasonable way to publish a result, but it is a snapshot. It cannot be filtered, it cannot be drilled into, and the moment the underlying data changes it is quietly wrong. Nobody in an operations meeting can ask it a follow-up question.
Atlas Charts is wired to the collection. Change the data and the chart changes. Add a filter and every chart on the dashboard responds. That difference — snapshot versus live view — is most of what separates a slide from a tool.
The real reason, though, is that it forces you to be explicit. A chart in Atlas Charts is nothing but an aggregation plus an encoding: which field goes on which visual channel, and how values are grouped. When you hand-draw a chart you can fudge that. When you build it in Charts you cannot — the tool makes you name the field and name the aggregation. Most bad charts are bad because nobody was ever forced to say those two things out loud.
You need the bookings in a real cluster. The free M0 tier is more than enough for fifteen thousand
documents. Download
data/uber_bookings.json
from this site, then load it.
Create a free cluster if you have not already — this is the same M0 cluster from the Lecture 11 lab. Database bdma, collection rides.
Import the documents. From a terminal, with your own connection string:
mongoimport --uri "mongodb+srv://USER:PASS@CLUSTER.mongodb.net/bdma" \
--collection rides \
--file uber_bookings.json \
--jsonArray
If you would rather not install the database tools, the Atlas UI will take the same file: Browse Collections → Insert Document → import JSON. It is slower but it works from a locked-down laptop.
Confirm the count before you go further. In mongosh, or the Atlas data explorer:
db.rides.countDocuments() // 15000
db.rides.findOne()
If you do not see exactly 15,000, stop and re-import. Every number on this site assumes that count, and a partial import produces charts that look plausible and are wrong — which is worse than charts that are obviously broken.
Note the shape of a document before you build anything. route.pickup
is nested. booked_at is an ISO string, not a BSON date. And on a failed
booking, booking_value, ratings and payment_method are
absent — not null, absent. All three of those facts change how you write the pipelines
below, and all three are the reason the pipelines look the way they do.
In the Atlas sidebar open Charts, then Data Sources → Add Data Source. Pick your cluster, then bdma.rides. Charts samples the collection to infer a schema; give it a moment.
Check the inferred types in the field panel. booked_at should come through as a string. That is expected and correct — we extract the hour from it in the pipeline rather than relying on Charts to parse it.
Create a dashboard: Dashboards → Add Dashboard. Call it Uber Ride Analytics. Every chart below goes on this one dashboard.
Each card below gives you the exact aggregation, the chart type to choose in Atlas, and which field belongs on which encoding channel. The workflow is the same every time: Add Chart, choose the data source, open the Query bar, paste the pipeline, then drag fields onto the encoding channels.
Where the pipeline goes. Atlas Charts gives you a query bar above the chart
builder. It accepts either a plain find filter — { status: "Completed" }
— or a full aggregation pipeline as an array. Paste the array exactly as shown, without the
surrounding db.rides.aggregate(…). The copy button on each card gives you the
wrapped version for mongosh; strip the wrapper when pasting into Charts.
Once a pipeline is in the query bar, the fields it outputs are what you encode — not the
original document fields. After pasting the hourly pipeline you will see hour,
bookings and failure_rate_pct in the field list, because that is what
the $project emits.
Six Number charts across the top of the dashboard, every one of them sharing a single pipeline.
The first chart to build, and the one that frames everything after it.
The largest single block of failure, broken into causes you could act on.
The hardest chart on the dashboard to build correctly, and the one carrying the finding.
A second, smaller chart whose only job is to prove the first one is not reading noise.
Context for everything else: is the problem getting worse, or has it always been this way?
Where the money actually comes from, which is not where the rides come from.
A simple chart with one genuinely necessary filter.
Where demand concentrates, and where it leaks.
Smaller than the driver side, but more diagnostic.
Charts drop onto the dashboard in the order you create them, which is almost never the order a reader needs. Rearrange them into an argument, the way Lecture 16 sets out: the KPI row first so the reader knows the scale, then the status mix so they know the problem exists, then the hourly chart and its volume floor so they know when, then cancellation reasons so they know why, and geography last so they know where to start.
Add a dashboard filter. Charts lets you define a filter that applies across every chart at once — vehicle_type is the useful one here. Being able to ask “does this pattern hold for Uber XL alone?” in one click is exactly the follow-up question a static image cannot answer.
Enable embedding if you want the dashboard on a web page: dashboard menu → Embed → Enable unauthenticated access, which gives you an <iframe> snippet.
Understand what you just did before you use it in anything real. Unauthenticated embedding makes the aggregated output publicly readable to anyone with the link. For this synthetic dataset that is harmless. For real booking data it would be a disclosure incident. Production embeds use authenticated embedding with a signed JWT and per-user filters.
Check your numbers against this site before you submit. Your status mix should read 9,343 completed and 2,698 driver cancellations. Your hourly chart should peak at 1,373 bookings at 18:00. Your volume-floor chart should put 17:00 on top at 39.92%. If any of those disagree, the pipeline is not what you think it is — and finding out why is the actual exercise.
| Trap | What it looks like | Fix |
|---|---|---|
| Averaging over absent fields | Average fare looks right but is computed over 15,000 documents instead of 9,343 | $avg skips missing values, so the average is fine — but any $sum ÷ count you write yourself is not. Divide by completed_bookings, never by total_bookings. |
| Ranking a rate with no volume floor | “Our worst hour is 03:00 at 43.48%” — on 46 bookings all year | Add { $match: { bookings: { $gte: 1000 } } } after the $project, and say the threshold out loud on the chart. |
| One axis for two units | The failure-rate line sits flat along the bottom of the hourly chart | Customize → Series → failure_rate_pct → Axis → Right. |
| Rounding inside the pipeline | Your chart shows 40.44% where this site shows 40.45% | Drop $round. MongoDB breaks ties to even, most display layers round half up, and the two disagree in the last digit. Format in the chart. |
| Counting failed as cancelled | Pickup cancellation rates come out around 39% instead of 33% | Incomplete rides travelled and earned a fare. They failed, but they were not cancelled. Decide which question you are answering and label the column accordingly. |
| Truncated value axis | A three-point difference between vehicle types looks like a cliff | Start value axes at zero unless you have a stated reason not to, and if you do not, say so on the chart. |
| A donut with twelve slices | Pickup locations rendered as a pie nobody can read | Donuts are for five categories or fewer where share is the question. Everything else is a bar chart. |
Lecture 16 takes the finished dashboard and asks whether it survives contact with a sceptical reader: is 17:00 a real pattern or an artifact, what would falsify it, and what single recommendation does it support. A dashboard that cannot answer those three questions is decoration. Bring yours.