- Reference
- Driver
- Reading and Writing
- Writing
Insert
Use the InsertOneAsync
method to insert a document. For example, when working with an IMongoCollection<BsonDocument>
., a BsonDocument
would be used.
var doc = new BsonDocument("x", 1);
await collection.InsertOneAsync(doc);
Upon a successful insertion (no exception was thrown), doc
will contain an _id
field. This identifer will be automatically generated if an _id
is not already present in the document. This is also true for mapped classes if they have an identifier property.
Note
For classes, it is possible to customize the Id generation process. See the reference on mapping.To insert multiple documents at the same time, the InsertManyAsync
method exists.
var docs = Enumerable.Range(0, 10).Select(i => new BsonDocument("x", i));
await collection.InsertManyAsync(docs);
As before, each of the documents will have their _id
field set.
Note
MongoDB reserves fields that start with_
and $
for internal use.
Update and Replace
There are 3 methods for updating documents. When intending to update an entire document, the ReplaceOneAsync
method should be used.
var newDoc = new BsonDocument { { "_id", 10 }, { "x", 2 } };
var result = await collection.ReplaceOneAsync(
filter: new BsonDocument("_id", 10),
replacement: newDoc);
important
_id
values in MongoDB documents are immutable. If you specify an _id
in the replacement document, it must match the _id
of the existing document.
When using a MongoDB update specification, the UpdateOneAsync
and UpdateManyAsync
methods are available.
var filter = new BsonDocument();
var update = new BsonDocument("$set", new BsonDocument("x", 1));
var result = await collection.UpdateOneAsync(filter, update);
Note
Even if multiple documents match the filter (as would be true in the above example), only one will be updated because we used UpdateOneAsync.To update all documents matching the filter:
var result = await collection.UpdateManyAsync(filter, update);
Upserts
To specify that you’d like to upsert a document, each method provides an optional UpdateOptions
parameter.
var filter = new BsonDocument();
var update = new BsonDocument("$set", new BsonDocument("x", 1));
var options = new UpdateOptions { IsUpsert = true };
var result = await collection.UpdateManyAsync(filter, update, options);
Note
If an identifier is not specified in the filter, replacement, or update, the server will generate an_id
of type ObjectId automatically.
Delete
Deleting documents takes 2 forms, DeleteOneAsync
and DeleteManyAsync
which, respectively, delete one or many documents matching the provided filter
.
var filter = new BsonDocument();
var result = await collection.DeleteOneAsync(filter);
// and
var result = await collection.DeleteManyAsync(filter);
Find And Modify
There are a certain class of operations using the findAndModify command from the server. This command will perform some operation on the document and return either the original version of the document as it was before the operation, or the new version of the document as it became after the operation. By default, the original version of the document is returned.
FindOneAndDelete
A single document can be deleted atomically using FindOneAndDeleteAsync
.
var filter = new BsonDocument("FirstName", "Jack");
var result = await collection.FindOneAndDeleteAsync(filter);
if (result != null)
{
Assert(result["FirstName"] == "Jack");
}
The above will find a document where the FirstName
is Jack
and delete it. It will then return the document that was just deleted.
FindOneAndReplace
A single document can be replaced atomically using FindOneAndReplaceAsync
.
var filter = new BsonDocument("FirstName", "Jack");
var replacementDocument = new BsonDocument("FirstName", "John");
var result = await collection.FindOneAndReplaceAsync(filter, doc);
if (result != null)
{
Assert(result["FirstName"] == "Jack");
}
The above will find a document where the FirstName
is Jack
and replace it with replacementDocument
. It will then return the document that was replaced.
FindOneAndUpdate
A single document can be updated atomically using FindOneAndUpdateAsync
.
var filter = new BsonDocument("FirstName", "Jack");
var update = Builders<BsonDocument>.Update.Set("FirstName", "John");
var result = await collection.FindOneAndUpdateAsync(filter, update);
if (result != null)
{
Assert(result["FirstName"] == "Jack");
}
The above will find a document where the FirstName
is Jack
and set its FirstName
field to John
. It will then return the document that was replaced.
Options
Each of the 3 operations has certain options available.
ReturnDocument
For Replacing and Updating, the ReturnDocument
enum can be provided. It allows you to choose which version of the document to return, either the original version as it was before the operation, or the modified version as it became after the operation.
For example:
var filter = new BsonDocument("FirstName", "Jack");
var update = Builders<BsonDocument>.Update.Set("FirstName", "John");
var options = new FindOneAndUpdateOptions<BsonDocument>
{
ReturnDocument = ReturnDocument.After
};
var result = await collection.FindOneAndUpdateAsync(filter, update, options);
if (result != null)
{
Assert(result["FirstName"] == "John");
}
Projection
A projection can be provided to shape the result. The easiest way to build the projection is using a projection builder.
Sort
Since only a single document is selected, for filters that could result in multiple choices, a sort should be provided and the first document in the sort order will be the one modified.
IsUpsert
For Replacing and Updating, IsUpsert
can be specified such that, if the document isn’t found, one will be inserted.
Bulk Writes
The BulkWriteAsync
method takes a variable number of WriteModel<>
instances and sends them to the server in the fewest possible number of batches. The size of a batch is limited by the maximum document size and each batch must consist of the same kind of write operations (i.e. deletes, inserts or updates).
For example, to run two delete operations with one call to the server:
var models = new WriteModel<BsonDocument>[]
{
new DeleteManyModel<BsonDocument>("{ x: 10 }"), // delete all documents where x == 10
new DeleteOneModel<BsonDocument>("{ x: 11 }") // delete 1 document where x == 11
};
await collection.BulkWriteAsync(models);
However, providing one insert and one delete would result in each getting sent in a different call to the server:
var models = new WriteModel<BsonDocument>[]
{
new InsertOneModel<BsonDocument>("{ _id: 1}"),
new DeleteOneModel<BsonDocument>("{ x: 11 }") // delete 1 document where x == 11
};
await collection.BulkWriteAsync(models); // will send one batch with the insert and one with the delete
Write Models
There are 6 types of write models:
Ordered and Unordered
Bulk writes can be ordered or unordered. The default is ordered.
- Ordered bulk writes execute all the operations in order and error out on the first error.
- Unordered bulk writes execute all the operations and report any errors at the end. Because the writes are unordered, the driver and/or server may re-order the operations in order to gain better performance.
var models = new WriteModel<BsonDocument>[]
{
new InsertOneModel<BsonDocument>(new BsonDocument("_id", 4)),
new InsertOneModel<BsonDocument>(new BsonDocument("_id", 5)),
new InsertOneModel<BsonDocument>(new BsonDocument("_id", 6)),
new UpdateOneModel<BsonDocument>(
new BsonDocument("_id", 1),
new BsonDocument("$set", new BsonDocument("x", 2))),
new DeleteOneModel<BsonDocument>(new BsonDocument("_id", 3)),
new ReplaceOneModel<BsonDocument>(
new BsonDocument("_id", 3),
new BsonDocument("_id", 3).Add("x", 4))
};
// 1. Ordered bulk operation - order of operation is guaranteed
await collection.BulkWriteAsync(models);
// 2. Unordered bulk operation - no guarantee of order of operation
await collection.BulkWriteAsync(models, new BulkWriteOptions { IsOrdered = false });