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
$set
and$unset
are 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
$push
can also accept modifiers like$each
to push multiple values, and$sort
to keep the array sorted.$pull
can remove elements based on conditions, not just specific values.$pop
only 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
$inc
and$mul
are 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
$inc
to decrement a field, and you can use fractions with$mul
to 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
$bit
operator only works on integer fields. Applying it to non-integer fields will result in an error.The
$bit
operator 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
$rename
operator will remove the old field name and its value from the document.$min
and$max
work 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
upsert
option can be used withupdateOne
,updateMany
, andfindOneAndUpdate
methods.The
returnNewDocument
option is specific tofindOneAndUpdate
and its variants (findOneAndReplace
,findOneAndDelete
).These options are atomic, ensuring that the operations are thread-safe.