Update in MongoDB
In MongoDB, the modify operation is part of the CRUD (Create, Read, Update, Delete) operations and focuses on updating existing documents within a collection. You can modify single or multiple documents using various update operators. Below are some common methods and operators used for modifying data:
updateOne()
Updates a single document that matches the query criteria.
db.collection.updateOne({ query }, { update })
updateMany()
Updates all documents that match the query criteria.
db.collection.updateMany({ query }, { update })
replaceOne()
Replaces a single document that matches the query criteria with a new document.
db.collection.replaceOne({ query }, { replacement })
findOneAndUpdate()
Finds a single document that matches the query criteria and updates it, returning either the original or the updated document.
db.collection.findOneAndUpdate({ query }, { update }, { options })
Common Update Operators
Field Update Operators
$set: Sets the value of a field.$unset: Removes a field.
In MongoDB, the $set and $unset operators are commonly used for updating documents. These operators allow you to modify specific fields within documents without affecting other existing fields. Here's how they work:
Using $set for Updating Fields
The $set operator replaces the value of a field with the specified value. If the field does not exist, $set will add a new field with the specified value.
Syntax
db.collection.updateOne(
{ <query conditions> },
{ $set: { <field1>: <value1>, <field2>: <value2>, ... } }
);
Example
Suppose you have a document like this in a collection named users:
{
"_id": 1,
"name": "Alice",
"age": 30
}
To update the age field to 31:
db.users.updateOne(
{ _id: 1 },
{ $set: { age: 31 } }
);
The document will now look like this:
{
"_id": 1,
"name": "Alice",
"age": 31
}
Using $unset to Remove Fields
The $unset operator removes the specified field from a document. If the field does not exist, $unset does nothing.
Syntax
db.collection.updateOne(
{ <query conditions> },
{ $unset: { <field1>: "", <field2>: "", ... } }
);
Example
Using the same document as before:
{
"_id": 1,
"name": "Alice",
"age": 31
}
To remove the age field:
db.users.updateOne(
{ _id: 1 },
{ $unset: { age: "" } }
);
The document will now look like this:
{
"_id": 1,
"name": "Alice"
}
Combining $set and $unset
You can combine $set and $unset in a single update operation.
Example
To update the name field to "Bob" and remove the age field:
db.users.updateOne(
{ _id: 1 },
{
$set: { name: "Bob" },
$unset: { age: "" }
}
);
The document will now look like this:
{
"_id": 1,
"name": "Bob"
}
Considerations
-
Both
$setand$unsetare idempotent operations. Repeating them produces the same result. -
These operators only affect the fields specified and leave the rest of the document unchanged.
Array Update Operators
$push: Adds an element to an array.$pop: Removes the first or last element from an array.$pull: Removes all instances of a value from an array.
In MongoDB, the $push, $pop, and $pull operators are used to manipulate array fields within documents. These operators allow you to add, remove, and modify elements in an array field.
Using $push to Add Elements
The $push operator appends a specified value to an array. If the array field does not exist, $push adds a new array field with the specified value as its first element.
Syntax
db.collection.updateOne(
{ <query conditions> },
{ $push: { <array field>: <value> } }
);
Example
Suppose you have a document like this:
{
"_id": 1,
"name": "Alice",
"hobbies": ["reading", "swimming"]
}
To add "cycling" to the hobbies array:
db.users.updateOne(
{ _id: 1 },
{ $push: { hobbies: "cycling" } }
);
The document will now look like this:
{
"_id": 1,
"name": "Alice",
"hobbies": ["reading", "swimming", "cycling"]
}
Using $pop to Remove Elements
The $pop operator removes the first or last element of an array. Pass -1 to remove the first element and 1 to remove the last element.
Syntax
db.collection.updateOne(
{ <query conditions> },
{ $pop: { <array field>: <-1 or 1> } }
);
Example
Using the same document as before:
{
"_id": 1,
"name": "Alice",
"hobbies": ["reading", "swimming", "cycling"]
}
To remove the last element ("cycling") from the hobbies array:
db.users.updateOne(
{ _id: 1 },
{ $pop: { hobbies: 1 } }
);
The document will now look like this:
{
"_id": 1,
"name": "Alice",
"hobbies": ["reading", "swimming"]
}
Using $pull to Remove Specific Elements
The $pull operator removes all instances of a value from an existing array.
Syntax
db.collection.updateOne(
{ <query conditions> },
{ $pull: { <array field>: <value or condition> } }
);
Example
Using the same document as before:
{
"_id": 1,
"name": "Alice",
"hobbies": ["reading", "swimming"]
}
To remove "reading" from the hobbies array:
db.users.updateOne(
{ _id: 1 },
{ $pull: { hobbies: "reading" } }
);
The document will now look like this:
{
"_id": 1,
"name": "Alice",
"hobbies": ["swimming"]
}
Considerations
-
$pushcan also accept modifiers like$eachto push multiple values, and$sortto keep the array sorted. -
$pullcan remove elements based on conditions, not just specific values. -
$poponly removes the first or last element, and it doesn't work based on a condition or specific value.
Arithmetic Update Operators
$inc: Increments a field by a specified value.$mul: Multiplies a field by a specified value.
In MongoDB, the $inc and $mul operators are used to increment and multiply the value of a field, respectively. These operators are useful for updating numerical fields in a document without having to read the document, modify it in your application, and then write it back to the database.
Using $inc to Increment Fields
The $inc operator increments a field by a specified value. If the field does not exist, $inc will create the field and set it to the specified value.
Syntax
db.collection.updateOne(
{ <query conditions> },
{ $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } }
);
Example
Suppose you have a document like this:
{
"_id": 1,
"name": "Alice",
"age": 30,
"score": 50
}
To increment the age by 1 and the score by 10:
db.users.updateOne(
{ _id: 1 },
{ $inc: { age: 1, score: 10 } }
);
The document will now look like this:
{
"_id": 1,
"name": "Alice",
"age": 31,
"score": 60
}
Using $mul to Multiply Fields
The $mul operator multiplies the value of a field by a specified number. If the field does not exist, $mul will create the field and set it to 0.
Syntax
db.collection.updateOne(
{ <query conditions> },
{ $mul: { <field1>: <number1>, <field2>: <number2>, ... } }
);
Example
Using the same document as before:
{
"_id": 1,
"name": "Alice",
"age": 31,
"score": 60
}
To multiply the age by 2 and the score by 3:
db.users.updateOne(
{ _id: 1 },
{ $mul: { age: 2, score: 3 } }
);
The document will now look like this:
{
"_id": 1,
"name": "Alice",
"age": 62,
"score": 180
}
Considerations
-
Both
$incand$mulare atomic operations, ensuring that the update is thread-safe. -
These operators work only on numerical fields. Attempting to use them on non-numeric fields will result in an error.
-
You can use negative numbers with
$incto decrement a field, and you can use fractions with$multo effectively divide a field.
Bitwise Update Operators
In MongoDB, the $bit operator is used for bitwise updates of integer fields. The operator supports bitwise AND, OR, and XOR (XOR is available starting from MongoDB 2.6). The $bit operator is useful when you need to change specific bits of an integer field without affecting the others.
Syntax
The general syntax for using the $bit operator is as follows:
db.collection.updateOne(
{ <query conditions> },
{ $bit: { <field>: { <operator>: <value> } } }
);
Here, <operator> can be and, or, or xor, and <value> is the integer value to apply the bitwise operation with.
Using $bit for Bitwise AND
The and operation performs a bitwise AND between the current value of the field and the specified value.
Example
Suppose you have a document with a field flags set to 5 (binary 0101):
db.users.updateOne(
{ _id: 1 },
{ $bit: { flags: { and: 3 } } } // 3 in binary is 0011
);
The flags field will be updated to 1 (binary 0001), which is the result of 0101 AND 0011.
Using $bit for Bitwise OR
The or operation performs a bitwise OR between the current value of the field and the specified value.
Example
Suppose you have a document with a field flags set to 5 (binary 0101):
db.users.updateOne(
{ _id: 1 },
{ $bit: { flags: { or: 2 } } } // 2 in binary is 0010
);
The flags field will be updated to 7 (binary 0111), which is the result of 0101 OR 0010.
Using $bit for Bitwise XOR
The xor operation performs a bitwise XOR between the current value of the field and the specified value.
Example
Suppose you have a document with a field flags set to 5 (binary 0101):
db.users.updateOne(
{ _id: 1 },
{ $bit: { flags: { xor: 3 } } } // 3 in binary is 0011
);
The flags field will be updated to 6 (binary 0110), which is the result of 0101 XOR 0011.
Considerations
-
The
$bitoperator only works on integer fields. Applying it to non-integer fields will result in an error. -
The
$bitoperator is an atomic operation, ensuring that the update is thread-safe. -
You can combine multiple bitwise operations in a single update query.
Other Update Operators
$rename: Renames a field.$min: Updates a field to the minimum of the current and specified values.$max: Updates a field to the maximum of the current and specified values.
In MongoDB, the $rename, $min, and $max operators are used to rename fields, and to update fields based on minimum or maximum value comparisons, respectively. These operators provide a way to perform specific types of updates atomically and efficiently.
Using $rename to Rename Fields
The $rename operator renames a field in a document. If the new field name already exists, the operator will overwrite the existing field's value.
Syntax
db.collection.updateOne(
{ <query conditions> },
{ $rename: { <old_field_name>: <new_field_name> } }
);
Example
Suppose you have a document like this:
{
"_id": 1,
"name": "Alice",
"age": 30
}
To rename the age field to years:
db.users.updateOne(
{ _id: 1 },
{ $rename: { "age": "years" } }
);
The document will now look like this:
{
"_id": 1,
"name": "Alice",
"years": 30
}
Using $min to Update Based on Minimum Value
The $min operator updates the value of a field to a specified value if the specified value is less than the current value of the field.
Syntax
db.collection.updateOne(
{ <query conditions> },
{ $min: { <field>: <value> } }
);
Example
Suppose you have a document like this:
{
"_id": 1,
"name": "Alice",
"score": 50
}
To update the score field to 40 only if 40 is less than the current score:
db.users.updateOne(
{ _id: 1 },
{ $min: { "score": 40 } }
);
The document will now look like this:
{
"_id": 1,
"name": "Alice",
"score": 40
}
Using $max to Update Based on Maximum Value
The $max operator updates the value of a field to a specified value if the specified value is greater than the current value of the field.
Syntax
db.collection.updateOne(
{ <query conditions> },
{ $max: { <field>: <value> } }
);
Example
Suppose you have a document like this:
{
"_id": 1,
"name": "Alice",
"score": 40
}
To update the score field to 50 only if 50 is greater than the current score:
db.users.updateOne(
{ _id: 1 },
{ $max: { "score": 50 } }
);
The document will now look like this:
{
"_id": 1,
"name": "Alice",
"score": 50
}
Considerations
-
The
$renameoperator will remove the old field name and its value from the document. -
$minand$maxwork with numerical as well as date fields. -
These operators are atomic, ensuring that the update is thread-safe.
Options for Modify Operations
upsert: Creates a new document if no documents match the query.returnNewDocument: Returns the updated document rather than the original.
In MongoDB, the upsert and returnNewDocument options are used to control the behavior of update and find-and-modify operations. These options offer flexibility in how documents are updated or returned.
Using upsert for Inserting or Updating
The upsert option stands for "update or insert." When you perform an update operation with upsert: true, MongoDB will update the document if it exists. If the document does not exist, MongoDB will insert a new document.
Syntax for updateOne
db.collection.updateOne(
{ <query conditions> },
{ <update operations> },
{ upsert: true }
);
Example
Suppose you want to set the score field to 100 for a user with _id: 1. If the user doesn't exist, you want to create a new document.
db.users.updateOne(
{ _id: 1 },
{ $set: { score: 100 } },
{ upsert: true }
);
If a document with _id: 1 exists, its score field will be set to 100. If the document doesn't exist, a new document with _id: 1 and score: 100 will be inserted.
Using returnNewDocument with findOneAndUpdate
The returnNewDocument option is used with the findOneAndUpdate method to control which version of the document is returned: the original document or the updated document.
Syntax
db.collection.findOneAndUpdate(
{ <query conditions> },
{ <update operations> },
{ returnNewDocument: true }
);
Example
Suppose you have a document like this:
{
"_id": 1,
"name": "Alice",
"score": 50
}
You want to increment the score by 10 and return the updated document.
const updatedDoc = db.users.findOneAndUpdate(
{ _id: 1 },
{ $inc: { score: 10 } },
{ returnNewDocument: true }
);
With returnNewDocument: true, the updatedDoc will contain the updated document:
{
"_id": 1,
"name": "Alice",
"score": 60
}
Considerations
-
The
upsertoption can be used withupdateOne,updateMany, andfindOneAndUpdatemethods. -
The
returnNewDocumentoption is specific tofindOneAndUpdateand its variants (findOneAndReplace,findOneAndDelete). -
These options are atomic, ensuring that the operations are thread-safe.