Unit 2: MongoDB Basics and CRUD Operations

CSE494 — Intelligent Nosql Databases 10 min read

I. MongoDB as a Document-Oriented Database

MongoDB is a document-oriented NoSQL database designed to store semi-structured data as BSON documents rather than rows in fixed relational tables. It was initially developed by 10gen in 2007 and released as an open-source database in 2009. MongoDB organizes data hierarchically as deployments, databases, collections, and documents.

  • Document model: Data is represented as JSON-like documents, while MongoDB stores documents internally in BSON.
  • Flexible schema: Documents in one collection may contain different fields, although applications should enforce a sensible logical structure.
  • Hierarchy: A MongoDB deployment contains databases; databases contain collections; collections contain documents.
  • CRUD principle: CRUD means Create, Read, Update, and Delete. MongoDB provides methods such as insertOne(), find(), updateOne(), and deleteOne().
  • Unique identifier: Every document normally contains an _id field. MongoDB automatically generates an ObjectId when the application does not provide one.
  • Atomicity: A single-document write is atomic. Multi-document transactions are available when operations must be coordinated across several documents.
  • Query style: Queries use selector documents such as { "age": { "$gte": 18 } }, where $gte means “greater than or equal to.”
  • Scalability: MongoDB supports replication for availability and sharding for distributing data across servers.

II. Databases — Logical Data Containers

A database is a named logical container for collections, indexes, users, and database-level configuration. MongoDB creates a database only when data is first stored in it.

A. Databases

Databases separate application data and provide an organizational and administrative boundary.

  • Selection: In the MongoDB shell, use university selects the database named university; it does not necessarily create it.
  • Creation trigger: The following command creates the database only after the insert is executed:
    JAVASCRIPT
      use university
      db.students.insertOne({ name: "Asha", program: "BCA" })
  • Listing: show dbs lists databases containing stored data; an empty selected database may not appear.
  • Inspection: db displays the current database, while show collections lists its collections.
  • Naming: Database names should be meaningful and avoid reserved characters such as /, \, ., ", $, and spaces.
  • Isolation: Collections with the same name can exist in different databases, such as university.students and training.students.
  • Deletion: db.dropDatabase() removes the current database and its collections. It is irreversible unless backups exist.
  • CRUD boundary: Create, read, update, and delete operations are normally issued through a selected database object, such as db.students.find().

III. Collections — Groups of Related Documents

A collection is a group of MongoDB documents and is broadly comparable to a table, but it does not require every document to have identical columns or structure.

A. Collections

Collections group related documents and provide the main target for CRUD operations, indexes, and validation rules.

  • Implicit creation: db.products.insertOne({ name: "Keyboard", price: 35 }) automatically creates products if it does not exist.
  • Explicit creation: A collection can be created with options:
    JAVASCRIPT
      db.createCollection("logs", {
        capped: true,
        size: 1048576,
        max: 5000
      })

    Here, capped enables a fixed-size collection, size is the maximum size in bytes, and max is the maximum document count.
  • Capped behavior: Capped collections preserve insertion order and overwrite older records when capacity is reached; they are useful for bounded logs.
  • Validation: validator and validationLevel can restrict document structure, for example requiring a numeric price field.
  • Dropping: db.logs.drop() removes one collection and its indexes, returning true when successful.
  • Namespaces: A collection is identified by the database and collection name together, such as university.students.
  • Natural grouping: Collections should represent access and lifecycle patterns. Frequently queried and independently managed data is often placed in a separate collection.

IV. Documents — BSON Records

A document is the basic unit of storage in MongoDB. It is a set of field-value pairs enclosed in braces and may contain nested documents and arrays.

A. Documents

Documents capture an entity and its related attributes in a structure that closely matches objects used in application code.

  • Structure: A document such as { name: "Ravi", age: 21 } contains fields name and age; field names are strings and values may have different BSON types.
  • Identifier: _id uniquely identifies a document within its collection. MongoDB creates an ObjectId("...") by default.
  • Nested data: A student’s address can be embedded:
    JAVASCRIPT
      {
        name: "Ravi",
        address: { city: "Pune", postalCode: 411001 },
        skills: ["Java", "MongoDB"]
      }
  • Create: db.students.insertMany([{ name: "Ravi" }, { name: "Meera" }]) inserts multiple documents and returns their generated identifiers.
  • Read: db.students.find({ age: { $gte: 18 } }, { name: 1, _id: 0 }) filters by age and projects only name. The value 1 includes a field and 0 excludes it.
  • Update: db.students.updateOne({ name: "Ravi" }, { $set: { semester: 4 } }) adds or changes semester without replacing the complete document.
  • Delete: db.students.deleteOne({ name: "Meera" }) removes the first matching document; deleteMany({}) removes all documents in the collection.
  • Replacement versus modification: replaceOne() replaces the complete matched document, whereas $set, $inc, $push, and $unset modify selected fields.
  • Limits: A BSON document has a maximum size of 16 MiB. Very large or unbounded arrays should generally be modeled separately.

V. BSON Data Types — Typed Binary JSON

BSON, or Binary JSON, is MongoDB’s binary-encoded representation of JSON-like documents. It extends JSON with additional types needed for database storage, querying, and indexing.

A. BSON Data Types

BSON data types determine how values are stored, compared, indexed, and returned to applications.

  • String: "MongoDB" stores textual data; string comparisons may depend on collation.
  • Double and Decimal128: 12.5 is commonly a double, while Decimal128("19.99") provides exact decimal arithmetic useful for financial values.
  • Integer types: Int32(25) and Long(9000000000) distinguish 32-bit and 64-bit integer ranges.
  • Boolean: true or false represents binary state, such as active: true.
  • Null: null explicitly represents an absent or unknown value, but it is distinct from a missing field in query behavior.
  • Array: ["red", "blue"] stores ordered values and can contain mixed types or embedded documents.
  • Embedded document: { city: "Delhi", country: "India" } groups related fields within a parent document.
  • ObjectId: ObjectId is a 12-byte identifier containing a timestamp component, a random value, and a counter; it is efficient for unique IDs.
  • Date: ISODate("2025-01-15T00:00:00Z") stores a UTC-based point in time. Applications should define timezone conventions clearly.
  • Binary data: Binary values store data such as file content, although GridFS is more suitable for files larger than the document limit.
  • Regular expression: /^A/i can match strings beginning with A, ignoring case; unanchored patterns may be expensive.
  • Type awareness: $type can find values of a particular BSON type:
    JAVASCRIPT
      db.records.find({ value: { $type: "string" } })
  • Schema implication: BSON supports flexibility, but using inconsistent types for the same logical field, such as storing price sometimes as a string and sometimes as a number, harms sorting and querying.

VI. Creating and Dropping Databases and Collections — Lifecycle Operations

Database and collection lifecycle operations establish or remove MongoDB storage structures and should be performed carefully, especially in production.

A. Creating and Dropping Databases and Collections

Creation is generally implicit, whereas dropping is explicit and permanently removes stored data.

  • Create database: Select a name with use inventory, then write data to materialize it:
    JAVASCRIPT
      use inventory
      db.items.insertOne({ sku: "K100", quantity: 40 })
  • Create collection: Use db.createCollection("items") when options, validation, or explicit initialization are required.
  • Drop collection: db.items.drop() removes items, its documents, and its indexes.
  • Drop database: db.dropDatabase() deletes the selected database, including all collections.
  • Safety check: Before destructive commands, verify the target with db.getName() and inspect show collections.
  • Permissions: Production users should receive only the privileges required for creation or deletion; administrative commands require suitable roles.
  • Operational effect: Dropping a collection or database invalidates dependent application assumptions and requires restoration from backup to recover data.
  • Initialization: Deployment scripts may create collections with validators and indexes so that development, testing, and production environments have consistent structures.

VII. Data Modeling in MongoDB — Designing for Access Patterns

Data modeling in MongoDB means choosing document boundaries, embedding, references, and field structures according to how the application reads and modifies data.

A. Data Modeling in MongoDB

The central modeling rule is to design documents around application access patterns rather than reproduce a normalized relational schema automatically.

  • Embedding: Store related data inside one document when it is read together and has a bounded size:
    JAVASCRIPT
      {
        orderId: 101,
        customer: { name: "Nila", city: "Chennai" },
        lines: [{ sku: "P1", quantity: 2 }, { sku: "P2", quantity: 1 }]
      }
  • Reference: Store an identifier such as customerId when related data is large, shared by many records, or updated independently.
  • One-to-one: Embed a bounded profile inside a user document when the profile is normally fetched with the user.
  • One-to-many: Embed small, bounded arrays; reference large or continuously growing relationships.
  • Many-to-many: Use references or a linking collection when both sides are numerous and independently queried.
  • Read locality: Embedding can retrieve an aggregate in one operation, reducing application-side joins.
  • Write locality: Separate documents when different parts change at different rates or require different permissions.
  • Duplication trade-off: Denormalizing a product name into an order speeds historical display but requires updates if the duplicated value is intended to remain current.
  • Array limitation: An unbounded comments or events array can approach the 16 MiB document limit and make updates increasingly costly.
  • Consistency: A single document provides atomic updates across its embedded fields; references may require transactions or carefully ordered application logic.
  • Schema validation: JSON Schema validation can enforce required fields and BSON types while retaining controlled flexibility.

VIII. Indexes and Query Optimization — Efficient Data Access

An index is a data structure that stores selected field values in an ordered form, allowing MongoDB to locate matching documents without scanning an entire collection.

A. Indexes and Query Optimization

Indexes improve read performance when their key patterns match common filters, sorts, and joins, but they consume memory and slow writes.

  • Default index: MongoDB automatically creates a unique ascending index on _id, written as { _id: 1 }; 1 means ascending order and -1 means descending order.
  • Single-field index: db.students.createIndex({ email: 1 }, { unique: true }) accelerates email equality searches and rejects duplicate values.
  • Compound index: { department: 1, age: -1 } supports queries beginning with department and can help sort by age; compound indexes follow the left-prefix principle.
  • Multikey index: Indexing an array field creates a multikey index, enabling queries such as { skills: "MongoDB" }.
  • Text index: createIndex({ description: "text" }) supports text search, subject to MongoDB text-search rules and language processing.
  • TTL index: { createdAt: 1 } with expireAfterSeconds automatically removes documents after a duration, useful for temporary records.
  • Partial or sparse indexes: These reduce indexed entries when only documents meeting a filter or containing a field should be indexed.
  • Index cost: Each additional index uses disk and RAM and must be updated during inserts, updates, and deletes.
  • Explain plan: db.students.find({ department: "CS" }).explain("executionStats") reports the selected plan and execution metrics.
  • Important metrics: COLLSCAN indicates a collection scan; IXSCAN indicates index scanning. totalDocsExamined and totalKeysExamined reveal work performed, while nReturned shows result count.
  • Optimization method: Index fields used in selective equality filters first, followed by sort fields and range fields when designing compound indexes.
  • Projection: Returning only required fields, such as { name: 1, _id: 0 }, reduces network transfer and may enable a covered query.
  • Query discipline: Avoid retrieving unnecessary documents, use limits and pagination, and inspect slow queries through profiling or monitoring.
  • Trade-off: An index is beneficial when its read savings exceed its storage and write-maintenance cost; unused indexes should be identified and removed carefully.