Skip to main content

Create Advanced Concepts

WriteConcern

In MongoDB, Write Concern describes the level of acknowledgment requested from MongoDB for write operations to a standalone mongod or to replica sets or to sharded clusters. In sharded clusters, mongos instances will pass the write concern on to the shards.

Parameters

The writeConcern object can contain the following fields:

  • w: The number of instances that need to acknowledge the write operation. It can be a number or a few special string values.

    • 0: No acknowledgment (fire-and-forget). Not recommended for most use-cases.
    • 1: Acknowledgment from a single instance (can be primary or secondary).
    • 2, 3, etc.: Acknowledgment from multiple instances.
    • "majority": Acknowledgment from the majority of instances in the replica set.
  • j: Journal acknowledgment. If set to true, MongoDB will wait for the write operation to be written to the journal before acknowledgment.

  • wtimeout: A time limit, in milliseconds, for the write concern. MongoDB will return an error if acknowledgment is not received within this time frame.

Examples

Here are some examples of how to use write concern in MongoDB:

  1. Default Write Concern

    db.collection.insertOne({ name: "Alice" });

    By default, MongoDB uses a write concern of { w: 1 }.

  2. Custom Write Concern

    db.collection.insertOne(
    { name: "Bob" },
    { writeConcern: { w: "majority", wtimeout: 5000 } }
    );

    This will wait for acknowledgment from the majority of instances and will timeout after 5000 milliseconds.

  3. No Acknowledgment

    db.collection.insertOne(
    { name: "Charlie" },
    { writeConcern: { w: 0 } }
    );

    This will not wait for any acknowledgment.

  4. Journal Acknowledgment

    db.collection.insertOne(
    { name: "David" },
    { writeConcern: { w: 1, j: true } }
    );

    This will wait for the write operation to be written to the journal.

Considerations

  • A stronger write concern (e.g., { w: "majority", j: true }) provides more durability but may increase latency.

  • A weaker write concern (e.g., { w: 0 }) may reduce latency but risks data loss.

  • Using a wtimeout can be useful to avoid hanging operations but may result in partial writes if the timeout is reached.

Ordered

The ordered option in MongoDB's insertMany() method controls the behavior of the insertion process when dealing with an array of documents. The ordered option can be set to either true or false.

Ordered (ordered: true)

By default, insertMany() operates in ordered mode (ordered: true). In this mode, MongoDB will insert the documents in the array serially, in the order they are listed. If an error occurs (e.g., a duplicate key error), the operation will halt, and no subsequent documents in the array will be inserted.

Example:

db.collection.insertMany([
{ _id: 1, name: 'Alice' },
{ _id: 2, name: 'Bob' },
{ _id: 1, name: 'Charlie' }, // Duplicate _id
{ _id: 3, name: 'David' }
], { ordered: true });

In this example, the insertion will stop at the document with _id: 1 (Charlie) due to the duplicate key error, and the document with _id: 3 (David) will not be inserted.

Unordered (ordered: false)

In unordered mode (ordered: false), MongoDB will insert the documents in parallel. If an error occurs, the insertMany() operation will continue to insert the remaining documents in the array.

Example:

db.collection.insertMany([
{ _id: 1, name: 'Alice' },
{ _id: 2, name: 'Bob' },
{ _id: 1, name: 'Charlie' }, // Duplicate _id
{ _id: 3, name: 'David' }
], { ordered: false });

In this example, even though the document with _id: 1 (Charlie) will cause a duplicate key error, the document with _id: 3 (David) will still be inserted.

Return Value

In both modes, insertMany() will return an object that contains information about the operation, including an array of _ids for the documents that were successfully inserted and any write errors that occurred.

Considerations

  • In ordered mode, the operation stops on the first error, which can be useful if the order of insertion or transactional integrity is important.
  • In unordered mode, all insertable documents will be inserted, which can be more efficient but may result in a partial insertion if some documents have errors.

Cursor

In MongoDB, a cursor is a pointer to the result set of a query. When you execute a query that returns multiple documents, MongoDB does not return all values at once; instead, it returns a cursor object. This cursor object allows you to iterate over the result set and retrieve documents one at a time, which is more efficient for large data sets.

Creating a Cursor

When you execute a query method like find(), MongoDB returns a cursor:

const cursor = db.collection('users').find({ age: { $gt: 21 } });

Cursor Methods

Here are some commonly used cursor methods:

Iteration Methods

  • forEach(): Iterates over all the documents for this cursor, applying a JavaScript function to each document.

    cursor.forEach(doc => {
    console.log(doc.name);
    });
  • next(): Retrieves the next document in the cursor.

    const nextDoc = await cursor.next();
  • toArray(): Converts the cursor to an array.

    const docsArray = await cursor.toArray();

Query Modifiers

  • limit(n): Limits the result set to n documents.

    cursor.limit(5);
  • skip(n): Skips the first n documents.

    cursor.skip(10);
  • sort(fieldOrSpec): Sorts the documents. The argument can be a field or a specification object.

    cursor.sort({ age: -1 });  // Descending sort by age

Projection

  • project(fieldOrSpec): Specifies which document fields to include or exclude.

    cursor.project({ name: 1, age: 1 });

Counting

  • count(): Counts the number of documents that match the query.

    const count = await cursor.count();

Aggregation

  • map(transform): Applies a function to each document in the cursor and collects the return values into an array.

    const names = cursor.map(doc => doc.name);
  • explain(): Provides information on the execution of the operation.

    const explanation = await cursor.explain();

Closing a Cursor

  • close(): Explicitly closes the cursor.

    await cursor.close();

Considerations

  • Cursors are stateful, meaning once you iterate over them, you can't reset them. You'll have to re-execute the query to get a new cursor.

  • Cursors can timeout on the server if left open for a long time without being accessed. This is to free up server resources.