Compound Operations
Overview
In this guide, you can learn how to perform compound operations.
Compound operations combine a read and write operation into a single operation. If you perform a read and write operation separately, there's a chance someone else may alter the document between both operations. MongoDB prevents this by placing a write lock on the document you are modifying for the duration of your compound operation.
MongoDB supports the following compound operations:
Tip
To learn how to perform compound operations on more than one document at a time, see the Transactions guide.
Sample Data
The examples in this guide use the following Course
struct as a model for documents
in the courses
collection:
type Course struct { Title string Enrollment int32 }
To run the examples in this guide, load the sample data into the
db.courses
collection with the following
snippet:
coll := client.Database("db").Collection("courses") docs := []interface{}{ Course{Title: "Representation Theory", Enrollment: 40}, Course{Title: "Early Modern Philosophy", Enrollment: 25}, Course{Title: "Animal Communication", Enrollment: 18}, } result, err := coll.InsertMany(context.TODO(), docs)
Each document contains a description of a university course that
includes the course title and maximum enrollment, corresponding to
the title
and enrollment
fields in each document.
Tip
Nonexistent Databases and Collections
If the necessary database and collection don't exist when you perform a write operation, the server implicitly creates them.
Find and Delete
The FindOneAndDelete()
method finds the first document that matches
the specified query filter and deletes it. The method returns a
SingleResult
containing the deleted document.
Note
The FindOneAndDelete()
method is an atomic operation, which means it prevents
any other write operations from changing the matching document until it
completes. The deleteOne()
method is also an atomic operation, but differs from
FindOneAndDelete()
in that you cannot specify a sort order for the
matched documents.
- To find a document and delete it in separate operations, call the
findOne()
method followed by thedeleteOne()
method.
Modify Behavior
You can modify the behavior of the FindOneAndDelete()
method by
passing in a FineOneAndDeleteOptions
. If you don't specify a
FineOneAndDeleteOptions
, the driver uses the default values for each
option.
The FineOneAndDeleteOptions
type allows you to configure options
with the following methods:
Method | Description |
---|---|
SetCollation() | The type of language collation to use when sorting results. Default: nil |
SetProjection() | The fields to include in the document returned. Default: nil |
SetSort() | The sort fields and directions to order the documents matched. Default: nil |
SetHint() | The index to use to scan for documents. Default: nil |
Example
The following example uses the FindOneAndDelete()
method
to match and delete the first document where the enrollment
field value is less than 20:
filter := bson.D{{"enrollment", bson.D{{"$lt", 20}}}} var deletedDoc Course err := coll.FindOneAndDelete(context.TODO(), filter).Decode(&deletedDoc) if err != nil { panic(err) } res, _ := bson.MarshalExtJSON(deletedDoc, false, false) fmt.Println(string(res))
{"title":"Animal Communication","enrollment":18}
Find and Update
The FindOneAndUpdate()
method finds the first document that matches
the specified query filter and updates it according to the update
document. The method returns a SingleResult
containing the matched
document.
Note
The FindOneAndUpdate()
method is an atomic operation, which means it prevents
any other write operations from changing the matching document until it
completes. The updateOne()
method is also an atomic operation, but differs from
FindOneAndUpdate()
in that you cannot specify a sort order for the
matched documents.
To find a document and update it in separate operations, call
the findOne()
method followed by the updateOne()
method.
Modify Behavior
You can modify the behavior of the FindOneAndUpdate()
method by
passing in a FineOneAndUpdateOptions
. If you don't specify a
FineOneAndUpdateOptions
, the driver uses the default values for each
option.
The FineOneAndUpdateOptions
type allows you to configure options
with the following methods:
Method | Description |
---|---|
SetArrayFilters() | The array elements the update applies to. Default: nil |
SetBypassDocumentValidation() | Whether to allow the write operation to opt-out of document level validation. Default: false |
SetCollation() | The type of language collation to use when sorting results. Default: nil |
SetProjection() | The fields to include in the document returned. Default: nil |
SetReturnDocument() | Whether to return the original or updated document in the SingleResult .Default: options.Before |
SetSort() | The sort fields and directions to order the documents matched. Default: nil |
SetUpsert() | Whether to insert a new document if the query filter doesn't match any documents. Default: false |
SetHint() | The index to use to scan for documents. Default: nil |
Example
The following example uses the FindOneAndUpdate()
method to
perform the following actions in order:
Matches the first document where the
title
field value includes "Modern"Updates the matched document's
enrollment
field value to32
Returns the updated document
filter := bson.D{{"title", bson.D{{"$regex", "Modern"}}}} update := bson.D{{"$set", bson.D{{"enrollment", 32}}}} opts := options.FindOneAndUpdate().SetReturnDocument(options.After) var updatedDoc Course err := coll.FindOneAndUpdate(context.TODO(), filter, update, opts).Decode(&updatedDoc) if err != nil { panic(err) } res, _ := bson.MarshalExtJSON(updatedDoc, false, false) fmt.Println(string(res))
{"title":"Early Modern Philosophy","enrollment":32}
Find and Replace
The FindOneAndReplace()
method finds the first document that
matches the specified query filter and replaces it with the replacement
document. The method returns a SingleResult
containing the matched
document.
Note
This method differs from the ReplaceOne()
method.
FindOneAndReplace()
performs a find and replace as a single
operation, and eliminates the possibility of someone altering a
document between both operations.
Modify Behavior
You can modify the behavior of the FindOneAndReplace()
method by
passing in a FineOneAndReplaceOptions
. If you don't specify a
FineOneAndReplaceOptions
, the driver uses the default values for each
option.
The FineOneAndReplaceOptions
type allows you to configure options
with the following methods:
Method | Description |
---|---|
SetBypassDocumentValidation() | Whether to allow the write operation to opt-out of document level validation. Default: false |
SetCollation() | The type of language collation to use when sorting results. Default: nil |
SetProjection() | The fields to include in the document returned. Default: nil |
SetReturnDocument() | Whether to return the original or replaced document in the SingleResult .Default: nil |
SetSort() | The sort fields and directions to order the documents matched. Default: nil |
SetUpsert() | Whether to insert a new document if the query filter doesn't match any documents. Default: false |
SetHint() | The index to use to scan for documents. Default: nil |
Example
The following example uses the FindOneAndReplace()
method to
perform the following actions in order:
Matches the first document where the
title
is "Representation Theory"Replaces the matched document with a new document where the
title
is "Combinatorial Theory" and theenrollment
is35
filter := bson.D{{"title", "Representation Theory"}} replacement := Course{Title: "Combinatorial Theory", Enrollment: 35} var outdatedDoc Course err := coll.FindOneAndReplace(context.TODO(), filter, replacement).Decode(&previousDoc) if err != nil { panic(err) } res, _ := bson.MarshalExtJSON(outdatedDoc, false, false) fmt.Println(string(res))
{"title":"Representation Theory","enrollment":40}
Additional Information
To learn more about performing the operations mentioned, see the following guides:
API Documentation
To learn more about any of the methods or types discussed in this guide, see the following API Documentation: