Indexes in MongoDB

  • Indexes in MongoDB are data structures that improve the efficiency of search queries. Without indexes, MongoDB must scan every document in a collection to find the required data, leading to slower performance, especially with large datasets. Indexes optimize queries by allowing MongoDB to quickly locate the necessary documents.
What is an Index?
  • An index is a special data structure that stores a small portion of the collection’s data in an easy-to-traverse form. The purpose of an index is to improve the speed of read operations. Indexes store the value of a specific field or set of fields, ordered by the value of the field.
  • For example, if you frequently search for documents based on the name field, indexing the name field allows MongoDB to quickly locate the documents that match the search condition.
Types of Indexes in MongoDB
  • MongoDB supports several types of indexes, each suited to different types of queries:
  • Single Field Index:
    • This is the most basic type of index. It is created on a single field in a collection.
    • Syntax:


    db.collection.createIndex({ field: 1 })

  • Here, 1 indicates ascending order. You can also use -1 for descending order.
  • For example, to create an index on the name field in the users collection:


    db.users.createIndex({ name: 1 })

  • Compound Index:
    • This index is created on multiple fields, allowing for queries involving more than one field.
    • Syntax:


    db.collection.createIndex({ field1: 1, field2: -1 })

  • For example, to create an index on name and age:


    db.users.createIndex({ name: 1, age: -1 })

  • MongoDB will use this index when you query based on both name and age, or just name.
  • Multikey Index:
    • This index is used for fields that hold arrays. Each element in the array is indexed.
    • Example: If a field tags contains an array of values like ["mongodb", "database", "index"], MongoDB creates a separate index entry for each array element.


    db.collection.createIndex({ tags: 1 })

  • Text Index:
    • This index is used to perform text searches. You can create a text index on string fields and perform efficient searches for keywords.
    • Syntax:


    db.collection.createIndex({ field: "text" })

  • For example, to create a text index on the description field:


    db.products.createIndex({ description: "text" })

  • You can now search for keywords in the description field:


    db.products.find({ $text: { $search: "laptop" } })

  • Hashed Index:
    • This index is useful for ensuring even distribution of data across a cluster when using sharding. It hashes the values of the indexed field to balance data across shards.
    • Syntax:


    db.collection.createIndex({ field: "hashed" })

  • For example, to create a hashed index on userId:


    db.users.createIndex({ userId: "hashed" })

  • Geospatial Index:
    • This index is used for geospatial queries (e.g., finding documents that contain geographic location data).
    • Syntax:


    db.collection.createIndex({ location: "2dsphere" })

  • This creates an index on a location field that stores geographic coordinates.
  • Unique Index:
    • This index ensures that all the values in the indexed field are unique across documents.
    • Syntax:


    db.collection.createIndex({ field: 1 }, { unique: true })

  • For example, to ensure that every user has a unique email:


    db.users.createIndex({ email: 1 }, { unique: true })

  • Wildcard Index:
    • Introduced in MongoDB 4.2, this index type is useful for indexing dynamic or arbitrary fields. Wildcard indexes allow you to create an index on all fields or a subset of fields.
    • Syntax:


    db.collection.createIndex({ "$**": 1 })

  • This will create an index on all fields in a document.
How to Create an Index in MongoDB
  • To create an index, use the createIndex() method. For example, to create an index on the name field in the users collection:


    db.users.createIndex({ name: 1 })

  • This command creates an ascending index on the name field.
Viewing Indexes
  • You can view the indexes on a collection using the getIndexes() method:


    db.collection.getIndexes()

  • Example:


    db.users.getIndexes()

  • This command will list all the indexes created for the users collection.
Dropping Indexes
  • To remove an index, use the dropIndex() method.
  • Syntax:

    db.collection.dropIndex("indexName")

  • Example:

    db.users.dropIndex("name_1")

  • To drop all indexes on a collection, including the default _id index, use:

    db.collection.dropIndexes()


Performance Impact of Indexes

Advantages:
  • Improved Query Performance: Indexes can drastically speed up queries that match indexed fields by reducing the amount of data MongoDB needs to scan.
  • Efficient Sorting: Indexes improve the performance of queries that use sort(), especially on large datasets.
  • Uniqueness: Unique indexes help enforce data integrity by ensuring that no two documents have the same value for the indexed field.
Disadvantages:
  • Slower Write Operations: Indexes add overhead to write operations (inserts, updates, deletes) because MongoDB needs to update the index every time a document is written.
  • Increased Storage: Indexes consume extra disk space. The more indexes you create, the more disk space will be used to store the index data.
  • Maintenance: Complex or redundant indexes can make your database harder to manage, leading to performance bottlenecks during heavy writes.
When to Use Indexes
  • Frequent Query Fields: Index fields that are often used in query filters (find()) or sorting (sort()).
  • Low Cardinality Fields: Avoid indexing fields with a low number of distinct values (e.g., gender with only two values: "male", "female"), as it may not provide a significant performance boost.
  • Unique Constraints: Use unique indexes to enforce the uniqueness of data in critical fields like emails or user IDs.
  • Optimizing Read-Heavy Operations: If your application performs more read operations than write operations, adding indexes on frequently queried fields is beneficial.
Example of Index Usage
  • Let's look at an example scenario where we index a users collection to optimize our queries:
  • Insert Sample Data:

    db.users.insertMany([
        { name: "Alice", age: 28, email: "alice@example.com" },
        { name: "Bob", age: 34, email: "bob@example.com" },
        { name: "Charlie", age: 25, email: "charlie@example.com" }
    ])

  • Create Index on name:

    db.users.createIndex({ name: 1 })

  • Now, MongoDB will use this index when querying for users by their name.
  • Query Using Index:

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

  • MongoDB will use the index to locate the document matching the name "Alice" more quickly.
  • Check Indexes:

    db.users.getIndexes()

  • This command will show the list of indexes created on the users collection.
  • Drop Index:

    db.users.dropIndex("name_1")

  • This will drop the index on the name field.
Conclusion
  • Indexes in MongoDB are crucial for optimizing query performance, particularly in large datasets. They allow the database to retrieve data faster by minimizing the number of documents that need to be scanned during a query. However, indexes come with trade-offs, such as slowing down write operations and consuming additional disk space. Therefore, it's essential to carefully plan and optimize the use of indexes based on the specific needs of your application.

CRUD Operations MongoDB Shell

  • CRUD operations in MongoDB are fundamental database tasks that involve Create, Read, Update, and Delete operations. These are typically performed on documents within collections, inside a database. MongoDB’s dynamic schema allows for flexible data storage, and these operations can be executed through the MongoDB shell (mongosh).
  • Below is a complete guide to performing CRUD operations through the MongoDB shell, including how to create a database and collection.
Create a Database in MongoDB
  • MongoDB creates a database only when data is inserted into it. To switch to or create a database:

    use myDatabase

  • If the database does not exist, MongoDB creates it as soon as you add data to a collection.
  • Example: If you switch to `myDatabase`, it will be created as soon as you insert a document.
Create a Collection
  • A collection is similar to a table in SQL databases, and documents are stored in collections. You can create a collection explicitly or implicitly by inserting data.
  • Explicit Collection Creation:

    db.createCollection("myCollection")

  • This will create an empty collection named `myCollection`.
  • Implicit Collection Creation (with document insertion):
    • MongoDB allows you to create a collection automatically when inserting data:

    db.myCollection.insertOne({ name: "John", age: 30 })

  • If `myCollection` does not exist, MongoDB will create it along with the document.
CRUD Operations in MongoDB
  • Create (Insert) Documents
    • MongoDB uses JSON-like documents for data storage. To insert documents into a collection:
  • Insert a single document:

    db.myCollection.insertOne({ name: "Alice", age: 25, profession: "Engineer" })

  • This command inserts one document into the `myCollection` collection.
  • Insert multiple documents:

    db.myCollection.insertMany([
      { name: "Bob", age: 28, profession: "Doctor" },
      { name: "Charlie", age: 35, profession: "Teacher" }
    ])

  • This inserts multiple documents into `myCollection`.
Read (Query) Documents
  • To retrieve or read data, MongoDB provides the `find()` method. You can query documents based on various criteria.
  • Show all documents:

    db.myCollection.find()

  • This will return all the documents in `myCollection`.
  • Find documents with a specific field:

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

  • This returns all documents where the `name` field is "Alice".
  • Query with conditions (e.g., `age` greater than 30):

    db.myCollection.find({ age: { $gt: 30 } })

  • This returns all documents where the `age` field is greater than 30.
  • Pretty print the results:

    db.myCollection.find().pretty()

  • This makes the output more readable by formatting it nicely.
  • Retrieve a single document:

    db.myCollection.findOne({ name: "Alice" })

  • This returns only the first document that matches the query criteria.
Update Documents
  • To update documents, you can use `updateOne()`, `updateMany()`, or `replaceOne()` depending on the number of documents you want to update and the type of update.
  • Update a single document:

    db.myCollection.updateOne(
      { name: "Alice" },  // Query to select the document
      { $set: { age: 26 } }  // Update operation
    )

  • This finds the document where `name` is "Alice" and updates her age to `26`.
  • Update multiple documents:

    db.myCollection.updateMany(
      { age: { $lt: 30 } },  // Query: Select all documents where age is less than 30
      { $set: { status: "Young" } }  // Update operation
    )

  • This updates all documents where `age` is less than 30 by adding a new field `status` with the value "Young".
  • Replace an entire document:

    db.myCollection.replaceOne(
      { name: "Alice" },  // Query: Find the document where name is "Alice"
      { name: "Alice", age: 28, profession: "Manager" }  // New document (replaces the old one)
    )

  • This replaces the entire document where the `name` is "Alice" with a new document.
Delete Documents
  • To remove documents from a collection, MongoDB provides `deleteOne()` and `deleteMany()`.
  • Delete a single document:

    db.myCollection.deleteOne({ name: "Alice" })

  • This deletes one document where the `name` is "Alice".
  • Delete multiple documents:

    db.myCollection.deleteMany({ age: { $lt: 30 } })

  • This deletes all documents where the `age` field is less than 30.
  • Delete all documents:

    db.myCollection.deleteMany({})

  • This deletes all the documents in the collection.
Additional Commands

Check the Current Database
  • To see which database you're currently working in:

    db

  • This command will return the name of the current database.
Show All Databases
  • To view a list of all available databases:

    show dbs


Show Collections in the Current Database
  • To display all the collections in the current database:

    show collections


Delete a Collection
  • To delete a collection, use the `drop()` method:

    db.myCollection.drop()

  • This will delete the `myCollection` from the database.
Delete a Database
  • To delete the current database:

    db.dropDatabase()

  • This deletes the entire database, including all its collections and documents.
  • Example: Complete Workflow
  • Create or switch to a database:

    use employeeDB

  • Create a collection:

    db.createCollection("employees")

  • Insert documents:

    db.employees.insertMany([
      { name: "Alice", age: 30, position: "Engineer" },
      { name: "Bob", age: 35, position: "Manager" }
    ])

  • Read documents:

    db.employees.find().pretty()

  • Update a document:

    db.employees.updateOne({ name: "Alice" }, { $set: { age: 31 } })

  • Delete a document:

    db.employees.deleteOne({ name: "Bob" })

  • Drop a collection:

    db.employees.drop()


Conclusion
  • CRUD operations are essential for interacting with MongoDB databases. These operations are straightforward in MongoDB, thanks to its dynamic schema and flexibility. You can perform these operations via the MongoDB shell (`mongosh`), MongoDB Compass, or programmatically through drivers (e.g., Node.js, Python). By using the commands described above, you can manage and manipulate your MongoDB databases effectively.

Creation, Display, and Deletion of DataBases, Collections, and Documents

  • Here's a detailed explanation of how to perform various operations in MongoDB, covering the creation, display, and deletion of databases, collections, and documents, as well as checking the current database and displaying its contents.
  • MongoDB operations are performed using the MongoDB shell (via the `mongo` command-line interface), but these commands can also be executed using MongoDB Compass or from a programming language using a driver.
Show Databases
  • To view all databases in MongoDB:

    show dbs

  • This command lists all the databases available in your MongoDB instance.
  • Example Output:

    admin    0.000GB
    config   0.000GB
    local    0.000GB
    mydb     0.000GB


Create a Database
  • MongoDB does not explicitly use the `CREATE DATABASE` command. Instead, a database is created implicitly when you insert data into it.
  • To create a new database, you must first switch to it (even if it doesn’t exist yet):

    use myNewDatabase

  • If `myNewDatabase` does not exist, MongoDB will create it as soon as data (such as a collection) is inserted into it.
Delete a Database
  • To delete an existing database, use the `dropDatabase()` command. First, switch to the database you want to delete:

    use myNewDatabase

  • Then, delete the database:

    db.dropDatabase()

  • This command deletes the current database, including all its collections and documents.
Create a Collection
  • A collection in MongoDB is a group of documents, similar to a table in relational databases. Collections are created either explicitly or implicitly when you insert data.
  • Explicit Collection Creation:

    db.createCollection("myCollection")

  • This creates an empty collection named `myCollection` in the current database.
Implicit Collection Creation:
  • You can also create a collection automatically by inserting a document into a non-existent collection:

    db.myCollection.insertOne({ name: "John Doe", age: 30 })

  • This command creates the collection `myCollection` if it doesn’t already exist and inserts a document into it.
Insert Documents
  • Documents in MongoDB are equivalent to rows in a relational database table. They are stored in collections.
  • Insert a Single Document:

    db.myCollection.insertOne({ name: "Alice", age: 25, profession: "Engineer" })

  • This inserts one document into the `myCollection` collection.
  • Insert Multiple Documents:

    db.myCollection.insertMany([
      { name: "Bob", age: 40, profession: "Teacher" },
      { name: "Charlie", age: 35, profession: "Doctor" }
    ])

  • This inserts multiple documents into the `myCollection` collection at once.
Check the Current Database
  • To check which database you are currently working in:

    db

  • This command returns the name of the current database.
  • Example Output:
    • myNewDatabase
Show Collections
  • To display all collections within the current database:

    show collections

  • This command lists all the collections in the current database.
Show Documents
  • To display all the documents in a collection, use the `find()` method.
  • Show All Documents in a Collection:

    db.myCollection.find()

  • This command retrieves and displays all the documents in the `myCollection` collection.
  • Example Output:

    {
        "_id": ObjectId("601f1e17c5efba45608f70d1"),
        "name": "Alice",
        "age": 25,
        "profession": "Engineer"
    }
    {
        "_id": ObjectId("601f1e17c5efba45608f70d2"),
        "name": "Bob",
        "age": 40,
        "profession": "Teacher"
    }
    {
        "_id": ObjectId("601f1e17c5efba45608f70d3"),
        "name": "Charlie",
        "age": 35,
        "profession": "Doctor"
    }

  • Show Documents with Specific Fields:
  • You can also query documents with specific criteria. For example, to show documents where the `age` is greater than `30`:

    db.myCollection.find({ age: { $gt: 30 } })

  • This query retrieves all documents where the `age` field is greater than 30.
  • Show Documents in a Pretty Format:
    • To make the document output easier to read, use the `pretty()` method:

    db.myCollection.find().pretty()

  • This will display each document in a more readable format.
Delete a Collection
  • To delete a collection, use the `drop()` method:

    db.myCollection.drop()

  • This command deletes the `myCollection` collection from the current database.
Delete Documents
  • To delete specific documents from a collection:
  • Delete a Single Document:

    db.myCollection.deleteOne({ name: "Alice" })

  • This deletes one document that matches the criteria (in this case, where the `name` is "Alice").
  • Delete Multiple Documents:

    db.myCollection.deleteMany({ age: { $lt: 30 } })

  • This deletes all documents where the `age` is less than 30.
Example Workflow
  • Here’s a basic workflow to create a database, add collections, insert documents, and display data:
  • Create or Switch to a Database:
    
    use myNewDatabase

  • Create a Collection:

    db.createCollection("users")

  • Insert Documents:

    db.users.insertMany([
      { name: "John", age: 28, profession: "Engineer" },
      { name: "Jane", age: 34, profession: "Designer" }
    ])

  • Show Collections:

    show collections

  • Display All Documents:

    db.users.find().pretty()

  • Delete a Document:

    db.users.deleteOne({ name: "John" })

  • Delete the Collection:

    db.users.drop()

  • Drop the Database:

    db.dropDatabase()


Conclusion
  • By using the above MongoDB commands, you can easily manage databases, collections, and documents. These operations form the core of working with MongoDB, whether you’re performing CRUD operations, managing schema, or querying data. MongoDB's dynamic schema allows you to work more flexibly with your data compared to traditional relational databases.

Phase 3 — Components Deep Dive

Chapter 1 — What We Are Going to Learn and Why In Phase 2 you learned what a component is and how to create one. You know that a component h...