The Practice Shop Database
From this lesson on, almost every example in the course runs against one small database called shop. It belongs to an online store that sells computer and mobile accessories to customers across India. Using the same data everywhere means you can compare results between lessons and you always know what a query should return.
In this lesson you will create the database with one script, look at a document from each collection and learn how the three collections connect.
The three collections
The shop database has three collections. A collection is a group of related documents, much like a table in SQL.
| Collection | Documents | What each document describes |
|---|---|---|
customers | 8 | A person who has an account: name, email, city, join date |
products | 10 | An item for sale: name, category, price in rupees, stock, tags |
orders | 12 | One purchase: who bought, when, the status, the items and the total |
The data is deliberately small. Twelve orders are enough to practise grouping, sorting and joining, and small enough that you can check every answer by eye.
The data script
Create a folder for your MongoDB practice files, for example C:\mongo on Windows or ~/mongo on Linux and macOS. Inside it, create a file named shop-data.js and paste the three parts below into it, one after another.
The first part switches to the shop database, deletes it if it already exists, and adds the customers:
// shop-data.js: builds the practice database used in this course
db = db.getSiblingDB('shop');
db.dropDatabase();
db.customers.insertMany([
{ _id: 1, name: 'Aarav Sharma', email: 'aarav@example.com', city: 'Jaipur', joined: ISODate('2025-01-14'), premium: true },
{ _id: 2, name: 'Priya Nair', email: 'priya@example.com', city: 'Kochi', joined: ISODate('2025-03-02'), premium: false },
{ _id: 3, name: 'Kabir Singh', email: 'kabir@example.com', city: 'Rohtak', joined: ISODate('2025-06-21'), premium: true },
{ _id: 4, name: 'Meera Iyer', email: 'meera@example.com', city: 'Pune', joined: ISODate('2025-09-10'), premium: false },
{ _id: 5, name: 'Rohan Gupta', email: 'rohan@example.com', city: 'Lucknow', joined: ISODate('2026-01-05'), premium: false },
{ _id: 6, name: 'Ananya Das', email: 'ananya@example.com', city: 'Pune', joined: ISODate('2026-02-18'), premium: true, referredBy: 1 },
{ _id: 7, name: 'Farhan Khan', email: 'farhan@example.com', city: 'Jaipur', joined: ISODate('2026-04-30'), premium: false, referredBy: 3 },
{ _id: 8, name: 'Isha Verma', email: 'isha@example.com', city: 'Kochi', joined: ISODate('2026-07-12'), premium: false }
]);The second part adds the products. Two of them carry an extra specs sub-document, because in MongoDB documents in the same collection do not need identical fields:
db.products.insertMany([
{ _id: 101, name: 'Wireless Mouse', category: 'Accessories', price: 799, stock: 120, rating: 4.3, tags: ['wireless', 'computer'] },
{ _id: 102, name: 'Mechanical Keyboard', category: 'Accessories', price: 3499, stock: 45, rating: 4.6, tags: ['computer', 'gaming'] },
{ _id: 103, name: '27-inch Monitor', category: 'Displays', price: 15999, stock: 12, rating: 4.4, tags: ['computer', 'office'], specs: { size: '27 inch', resolution: '2560x1440' } },
{ _id: 104, name: 'USB-C Cable', category: 'Accessories', price: 299, stock: 300, rating: 4.1, tags: ['cable', 'mobile'] },
{ _id: 105, name: 'Bluetooth Earbuds', category: 'Audio', price: 2499, stock: 60, rating: 4.0, tags: ['wireless', 'mobile', 'music'] },
{ _id: 106, name: 'Laptop Stand', category: 'Accessories', price: 1299, stock: 0, rating: 4.5, tags: ['office'] },
{ _id: 107, name: 'Portable SSD 1TB', category: 'Storage', price: 6999, stock: 25, rating: 4.7, tags: ['storage', 'backup'], specs: { capacity: '1TB', port: 'USB-C' } },
{ _id: 108, name: 'Learn Python Book', category: 'Books', price: 649, stock: 40, rating: 4.8, tags: ['books', 'learning'] },
{ _id: 109, name: 'HD Webcam', category: 'Accessories', price: 1899, stock: 18, rating: 3.9, tags: ['video', 'office'] },
{ _id: 110, name: 'Power Bank 20000mAh', category: 'Mobile', price: 1499, stock: 75, rating: 4.2, tags: ['mobile', 'travel'] }
]);The third part adds the orders and prints a count of each collection so you can see that everything worked:
db.orders.insertMany([
{ _id: 1001, customerId: 1, date: ISODate('2026-08-03T10:15:00Z'), status: 'delivered', payment: 'UPI',
items: [{ productId: 101, name: 'Wireless Mouse', price: 799, qty: 1 }, { productId: 104, name: 'USB-C Cable', price: 299, qty: 2 }], total: 1397 },
{ _id: 1002, customerId: 2, date: ISODate('2026-08-07T14:40:00Z'), status: 'delivered', payment: 'card',
items: [{ productId: 103, name: '27-inch Monitor', price: 15999, qty: 1 }], total: 15999 },
{ _id: 1003, customerId: 1, date: ISODate('2026-08-15T09:05:00Z'), status: 'delivered', payment: 'UPI',
items: [{ productId: 107, name: 'Portable SSD 1TB', price: 6999, qty: 1 }], total: 6999 },
{ _id: 1004, customerId: 3, date: ISODate('2026-08-21T18:30:00Z'), status: 'delivered', payment: 'COD',
items: [{ productId: 102, name: 'Mechanical Keyboard', price: 3499, qty: 1 }, { productId: 101, name: 'Wireless Mouse', price: 799, qty: 1 }], total: 4298 },
{ _id: 1005, customerId: 4, date: ISODate('2026-09-02T11:20:00Z'), status: 'cancelled', payment: 'card',
items: [{ productId: 105, name: 'Bluetooth Earbuds', price: 2499, qty: 1 }], total: 2499 },
{ _id: 1006, customerId: 5, date: ISODate('2026-09-09T16:45:00Z'), status: 'delivered', payment: 'UPI',
items: [{ productId: 108, name: 'Learn Python Book', price: 649, qty: 2 }], total: 1298 },
{ _id: 1007, customerId: 6, date: ISODate('2026-09-18T12:10:00Z'), status: 'shipped', payment: 'UPI',
items: [{ productId: 110, name: 'Power Bank 20000mAh', price: 1499, qty: 1 }, { productId: 104, name: 'USB-C Cable', price: 299, qty: 1 }], total: 1798 },
{ _id: 1008, customerId: 3, date: ISODate('2026-09-25T19:55:00Z'), status: 'delivered', payment: 'UPI',
items: [{ productId: 109, name: 'HD Webcam', price: 1899, qty: 1 }], total: 1899 },
{ _id: 1009, customerId: 2, date: ISODate('2026-10-04T08:30:00Z'), status: 'shipped', payment: 'card',
items: [{ productId: 105, name: 'Bluetooth Earbuds', price: 2499, qty: 2 }], total: 4998 },
{ _id: 1010, customerId: 7, date: ISODate('2026-10-11T13:00:00Z'), status: 'pending', payment: 'COD',
items: [{ productId: 106, name: 'Laptop Stand', price: 1299, qty: 1 }, { productId: 101, name: 'Wireless Mouse', price: 799, qty: 1 }], total: 2098 },
{ _id: 1011, customerId: 1, date: ISODate('2026-10-19T20:25:00Z'), status: 'pending', payment: 'UPI',
items: [{ productId: 102, name: 'Mechanical Keyboard', price: 3499, qty: 1 }], total: 3499 },
{ _id: 1012, customerId: 4, date: ISODate('2026-10-24T10:50:00Z'), status: 'delivered', payment: 'UPI',
items: [{ productId: 108, name: 'Learn Python Book', price: 649, qty: 1 }, { productId: 110, name: 'Power Bank 20000mAh', price: 1499, qty: 1 }], total: 2148 }
]);
print('customers:', db.customers.countDocuments());
print('products:', db.products.countDocuments());
print('orders:', db.orders.countDocuments());Load the data
Open a terminal in the folder that holds shop-data.js and start mongosh (for Atlas, use your connection string as shown in Install MongoDB, mongosh & Compass). Then run the script with load() and switch to the new database:
load('shop-data.js')
use shopcustomers: 8 products: 10 orders: 12 true switched to db shop
The three lines come from the print() calls, true is the return value of load(), and the last line confirms that db now points at shop. If load() cannot find the file, give the full path with forward slashes, such as load('C:/mongo/shop-data.js').
A first look at each collection
Fetch one order by its _id with findOne(). You will learn the method properly in Find Documents; for now, just read the shape of the result:
db.orders.findOne({ _id: 1001 }){
_id: 1001,
customerId: 1,
date: ISODate('2026-08-03T10:15:00.000Z'),
status: 'delivered',
payment: 'UPI',
items: [
{ productId: 101, name: 'Wireless Mouse', price: 799, qty: 1 },
{ productId: 104, name: 'USB-C Cable', price: 299, qty: 2 }
],
total: 1397
}Order 1001 belongs to customer 1, Aarav. It contains an array of two items, and each item is a small embedded document. The total is 799 + 2 × 299 = ₹1,397. Notice that mongosh shows the date in full, with milliseconds and a Z at the end, which means UTC time.
How the collections connect
The collections link to each other through _id values, in the same way a foreign key links SQL tables:
orders.customerIdholds the_idof a document incustomers.orders.items.productIdholds the_idof a document inproducts.customers.referredBy, which only two customers have, holds the_idof the customer who referred them.
Each order item also copies the product's name and price. That is a deliberate design choice, not an accident. If the shop raises the price of the mouse next month, Aarav's old order must still show the ₹799 he actually paid. You will meet this idea again in Schema Design: Embed or Reference.
A few facts about the data are worth remembering, because many later results depend on them:
- Isha (customer 8) has no orders yet.
- The Laptop Stand (product 106) is out of stock: its
stockis 0. - Order 1005 is
cancelled, two orders arependingand two areshipped; the other seven aredelivered. - The
_idvalues are small numbers chosen by us. Real applications usually let MongoDB create anObjectId, as you saw in BSON Data Types & ObjectId. Readable numbers simply keep the outputs short.
Common mistakes
- Forgetting
use shop. If your prompt still saystest>, every query looks in the emptytestdatabase and returns nothing. Switch first. - Running the script from the wrong folder.
load()looks for a relative path in the folder where you startedmongosh. Use the full path if in doubt. - Breaking the file while pasting. A missing comma or bracket gives a
SyntaxErrorwith a line number. Compare that line with the code above. - Changing the data and forgetting. If a result does not match the lesson, reload the script and try again.
Key points
- The
shopdatabase has three collections:customers(8),products(10) andorders(12). - One script,
shop-data.js, creates everything; run it withload()and thenuse shop. - Running the script again resets the database to its starting state.
- Orders reference customers by
customerIdand products byitems.productId. - Order items copy the product name and price so old orders keep the price that was paid.
Exercise
Load the shop data, switch to the shop database and fetch the product whose _id is 107. Then fetch the customer whose _id is 6 and note which field she has that most other customers do not.
Show solution
load('shop-data.js')
use shop
db.products.findOne({ _id: 107 })
db.customers.findOne({ _id: 6 })Product 107 is the Portable SSD 1TB at ₹6,999 with a specs sub-document. Customer 6 is Ananya Das from Pune; she has a referredBy field with the value 1, because Aarav referred her. Only Ananya and Farhan have this field.
Quick Quiz
1. Which collection stores the price a customer actually paid for an item?
Each order item copies the price at the time of purchase, so later price changes do not alter old orders.
2. What does running load('shop-data.js') a second time do?
The script calls db.dropDatabase() before inserting, so it always resets to the same starting state.
3. How does an order point to the customer who placed it?
customerId is a reference to the _id of a document in the customers collection.
Learn MongoDB with a mentor
Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
