MongoDB: Documents & Collections

Understand MongoDB's core terminology: documents and collections. Learn how data is stored in flexible, JSON-like documents and grouped into collections, and why this model powers modern applications. Hands-on steps included.

Focus: MongoDB documents collections terminology

Sponsored

You’ve heard the buzzwords — NoSQL, flexible schema, JSON documents — but when you actually open the MongoDB shell and type db.users.find(), you see a wall of curly braces and wonder what you’re really looking at. The key to making MongoDB click is nailing its core terminology: every chunk of data is a document, and documents are grouped into collections. Once you lock in these two concepts, almost everything else in MongoDB — queries, indexes, aggregations, even replication — becomes an extension of the same simple mental model. By the end of this lesson, you’ll not only be fluent in MongoDB’s vocabulary, but you’ll be able to create your own documents and collections from scratch with zero guesswork.

The problem this lesson solves

When you come from a relational database background (like MySQL or PostgreSQL), you’re used to thinking in rigid tables, rows, and columns. Every row must have the same structure, every column is pre-defined, and changing your schema means running ALTER TABLE migrations that can bring your app down. MongoDB doesn't work that way, and that difference confuses beginners who try to force relational thinking onto it.

The pain is real: you know what you want to store, but you don’t know how to store it. You type db and see test, you insert a record and see something called a ObjectId("..."), and you have no idea what you just did. Tutorials throw around terms like document, collection, and field as if they're obvious — but they’re not. You build a mental model on guesswork, and that leads to silly bugs later, like accidentally storing a number as a string or querying a field that doesn’t exist.

This lesson solves that problem. By the time you finish, you’ll be able to look at any MongoDB shell output and confidently say: “That’s a document, that’s a field, that’s a collection, and here’s how they fit together.” You’ll stop guessing and start knowing.

Core concept / mental model

Think of a document like a card in a Rolodex. Each card holds information about one person, product, or event, and each card can have slightly different details — some cards have birthdays, others don’t. A collection is the whole box of cards, where each card represents one record.

What exactly is a document?

  • A document is a single unit of data — the MongoDB equivalent of a row in a relational table.
  • It’s structed as BSON (Binary JSON), which is a superset of JSON. Practically, you write documents in JSON-like format in the shell or in your application code.
  • Documents are composed of fields (also called keys or attributes) and values. A field can hold a string, a number, a boolean, an array, another document (embedded subdocument), or special types like dates and ObjectIds.

What is a collection?

  • A collection is a group of related documents — the MongoDB equivalent of a table.
  • Unlike a table, a collection doesn’t enforce a schema. Two documents in the same collection can have completely different fields.
  • In practice, you still put similar data together (e.g., all user profiles in a users collection) for performance and clarity, but you’re not forced to.

The trio: database, collection, document

A database is the outermost container (e.g., mydb). Inside a database, you have one or more collections. Inside each collection, you have documents. That’s it. No joins, no foreign keys — though you can still reference other documents if you want.

Here’s a simple diagram in words:

mydb (database)
  └─ users (collection)
       ├─ { "_id": 1, "name": "Alice", "age": 30 }
       ├─ { "_id": 2, "name": "Bob", "age": 25, "email": "bob@example.com" }
       └─ { "_id": 3, "name": "Carol" }

Pro tip: Every document must have a unique _id field. If you don’t provide one, MongoDB generates an ObjectId for you automatically.

How it works step by step

Let’s walk through the mechanics of how MongoDB stores and retrieves this data.

  1. You connect to a MongoDB instance — either a local server or a cloud cluster (like Atlas).
  2. You select a database — MongoDB creates a database on the fly if it doesn’t exist.
  3. You choose a collection — similarly, MongoDB creates a collection the first time you insert a document into it.
  4. You insert a document — you provide an object (in JSON-like syntax), and MongoDB validates it and assigns a unique _id.
  5. You query the collection — MongoDB scans (or uses an index) to find matching documents and returns them as JSON-like documents.

The key thing to internalize is that collections and databases don’t exist until you add data to them. In SQL, you have to CREATE TABLE first. In MongoDB, you just insert.

Example from the shell

// Switch to (or create) a database called "shop"
use shop

// Insert a product document into a "products" collection
// If the collection doesn't exist, it gets created automatically
db.products.insertOne({
  name: "Wireless Mouse",
  price: 29.99,
  inStock: true
})

Output:

{
  "acknowledged": true,
  "insertedId": ObjectId("60d5f9f5d4f8a02a3c4b8c3a")
}

You just created a document inside a collection. Note the insertedId — MongoDB auto-generated it for you.

Hands-on walkthrough

Time to get your hands dirty. We’ll use the mongosh shell (the modern MongoDB shell) to perform real operations. If you don’t have MongoDB installed, you can use MongoDB Atlas’s free tier or a Docker container — see the troubleshooting section for a quick setup.

Step 1: Insert multiple documents

Let’s create a collection of users, but deliberately give them different fields to show the flexibility of documents.

use myapp

db.users.insertMany([
  { name: "Alice", age: 30, email: "alice@example.com" },
  { name: "Bob", age: 25 },
  { name: "Carol", age: 35, address: { city: "Paris", zip: "75001" } }
])

The output will show insertedIds for each document. Notice the third document has an address field that contains another document (an embedded subdocument). That’s completely allowed.

Step 2: Query all documents

To see what you stored, query the collection:

db.users.find()

Output (simplified):

[
  { _id: ObjectId("..."), name: "Alice", age: 30, email: "alice@example.com" },
  { _id: ObjectId("..."), name: "Bob", age: 25 },
  { _id: ObjectId("..."), name: "Carol", age: 35, address: { city: "Paris", zip: "75001" } }
]

Notice each document has an _id assigned automatically. The documents don’t share the same fields — Bob has no email, Carol has an address, Alice has neither. That’s the flexibility of MongoDB documents.

Step 3: Query with a filter

Query for documents where the name field equals "Alice":

db.users.find({ name: "Alice" })

Output:

[ { _id: ObjectId("..."), name: "Alice", age: 30, email: "alice@example.com" } ]

The { name: "Alice" } is a query filter document — it’s just a document that specifies which fields to match. This is the first time you’re using documents both for storage and for queries.

Step 4: Count documents in a collection

db.users.countDocuments()

Output:

3

This tells you how many documents are in the users collection.

Pro tip: The insertMany() method is efficient for bulk inserts and returns the IDs of all documents. Use it whenever you insert multiple records at once.

Compare options / when to choose what

Now that you understand documents and collections, you might wonder: when should you use an embedded document versus a separate collection? And when should you use MongoDB at all versus a SQL database?

Option When to use it Example
Embedded document When you always access the sub-data together with the parent, and the sub-data has a one-to-one or one-to-many relationship that isn’t huge. A user’s address inside the user document.
Separate collection When the sub-data is large, shared across many documents, or accessed independently. A orders collection that references a user via userId.
MongoDB (document DB) When you have flexible or evolving schemas, need horizontal scaling, or want fast writes without joins. A product catalog where each product has different spec fields.
SQL database When you need complex multi-row transactions, strict schemas, or heavy reporting with joins. An accounting system with ledger tables.

As a rule of thumb: start with an embedded document, and split it out into a separate collection only if you start to see pain (e.g., data duplication, query complexity, huge arrays). This keeps your model simple and performant.

Troubleshooting & edge cases

Even with a clear mental model, you’ll hit a few quirks. Let’s address common ones.

1. “Database or collection doesn’t exist” when querying

If you run db.users.find() and get no results, it might be because the collection doesn't exist yet. Remember: collections are created lazily — only when you insert your first document. If you just created the database but never inserted data, an empty result is normal.

Fix: Insert a document first, then query.

2. Duplicate _id error

If you try to insert a document with a _id that already exists in the collection, you’ll get a duplicate key error:

E11000 duplicate key error collection: myapp.users index: _id_ dup key: { _id: 1 }

This happens when you specify _id manually and clash with an existing one.

Fix: Let MongoDB generate the ObjectId automatically, or use a unique value like a UUID that you control.

3. Data types: numbers vs strings

A common beginner mistake is saving a number as a string. For example:

db.users.insertOne({ name: "Dave", age: "30" })  // age is a string

Now age is a string, and sorting or comparing it numerically will behave unexpectedly (e.g., "30" < "9" in string comparison).

Fix: Be deliberate about your data types. Always use numbers for numeric fields, booleans for flags, and dates for dates.

4. Embedded documents get too big

If you embed an array that grows without bound (e.g., a list of user comments), you might hit the 16 MB document size limit or performance problems.

Fix: Use a separate collection and reference the parent document via an ID.

What you learned & what's next

You’ve internalized the two most important terms in MongoDB: document and collection. You now know that a document is a single flexible record stored as BSON, and a collection is a group of such documents within a database. You can insert and query documents, you understand the role of the _id field, and you know when to embed versus separate into collections. Most importantly, you’ve connected this terminology to how MongoDB actually stores data, which is the foundation for everything you’ll build next.

Your next step is to learn how to query MongoDB documents effectively — filtering, projecting, and sorting data with the query language. You’ll take the same find() command you used here and turn it into a powerful tool to answer business questions from your data.

Now, let’s see if you can apply this knowledge.

Try it yourself

Open your MongoDB shell and complete these exercises:

  1. Create a new database called library and a collection books.
  2. Insert three book documents, each with a different set of fields (e.g., one with an author, one with a publication year, one with an array of genres).
  3. Query all books, then query for a book by title.
  4. Count the documents in the collection.

This hands-on practice will cement the mental model — after you do it, you’ll never confuse a document with a collection again.

Practice recap

Open your MongoDB shell and create a library database with a books collection. Insert three books with different fields (e.g., one has author, another has genres array), then query them using db.books.find({title: "..."}) and count with countDocuments(). This will turn the terrain of documents and collections into second nature.

Common mistakes

  • Thinking a collection is a table and trying to enforce a strict schema. MongoDB collections don’t care about uniform fields across documents.
  • Performing queries on a collection that doesn't exist yet — remember collections are created lazily when you insert the first document, so an empty result may just mean no data.
  • Storing numeric values as strings (e.g., "30" instead of 30), causing comparisons and sorting to behave incorrectly.
  • Embedding unlimited subdocuments or arrays and hitting the 16 MB document size limit — know when to use a separate collection.

Variations

  1. Use the MongoDB Atlas web UI instead of the shell to visually inspect documents and collections, which can make the concept more concrete for visual learners.
  2. Access MongoDB through a driver (e.g., PyMongo in Python) to see documents as Python dictionaries, reinforcing the idea that documents are just data structures.
  3. Use MongoDB Compass, the GUI, to create databases and collections point-and-click without writing shell commands.

Real-world use cases

  • Storing user profiles where each user may have optional fields like address, phone, or preferences — documents handle missing fields gracefully.
  • Building a product catalog for an e-commerce site where each product type has different specifications and attributes.
  • Logging application events with variable structure (e.g., an event may have a stackTrace only on errors) into a single collection.

Key takeaways

  • A document is the basic unit of data in MongoDB, stored as BSON and composed of fields and values.
  • A collection is a group of related documents, like a table, but without a rigid schema.
  • Databases contain collections, and collections and databases are created on demand when you first insert data.
  • Every document must have a unique _id field — MongoDB auto-generates it if you don't provide one.
  • Documents allow embedded subdocuments and arrays for flexible data modeling, but be mindful of the 16 MB limit and performance trade-offs.
  • The find() command returns documents that match a filter — the filter itself is just another document.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.