Rebuild It in Atlas Charts

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.

bdma.rides 10 pipelines 9 charts + KPI row Lecture 15 lab
On this page
  1. Why rebuild something that already works
  2. Getting the data into Atlas
  3. Creating the Charts data source
  4. Nine charts and a KPI row
  5. Assembling and embedding the dashboard
  6. Traps that cost people marks

Why rebuild something that already works

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.

Getting the data into Atlas

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.

1

Create a free cluster if you have not already — this is the same M0 cluster from the Lecture 11 lab. Database bdma, collection rides.

2

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.

3

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.

Creating the Charts data source

4

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.

5

Create a dashboard: Dashboards → Add Dashboard. Call it Uber Ride Analytics. Every chart below goes on this one dashboard.

Nine charts and a KPI row

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.

The headline numbers

KPI row

Six Number charts across the top of the dashboard, every one of them sharing a single pipeline.

Where bookings end up

Booking status mix

The first chart to build, and the one that frames everything after it.

Driver cancellation reasons

The largest single block of failure, broken into causes you could act on.

Demand across the day

Demand and failure by hour

The hardest chart on the dashboard to build correctly, and the one carrying the finding.

The volume floor

A second, smaller chart whose only job is to prove the first one is not reading noise.

The year in shape

Monthly bookings and revenue

Context for everything else: is the problem getting worse, or has it always been this way?

Product and payment mix

Revenue by vehicle type

Where the money actually comes from, which is not where the rides come from.

Payment method mix

A simple chart with one genuinely necessary filter.

Geography and customer voice

Top pickup points

Where demand concentrates, and where it leaks.

Customer cancellation reasons

Smaller than the driver side, but more diagnostic.

Assembling and embedding the dashboard

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.

6

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.

7

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.

Traps that cost people marks

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.
Where this goes next

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.