Links
Access to a collection
|
// nuget packages: MongoDB.Driver
var mongoClient = new MongoClient("MONGODB_CONNECTION_STRING");
var database = mongoClient.GetDatabase("DB_NAME");
var collection = database.GetCollection<MyClass>("COLLECTION_NAME");
|
Dependency injection
Program.cs
|
builder.Services
.Configure<MongoConfiguration>(builder.Configuration.GetSection("Mongo"))
.AddSingleton<IMongoClient>(x =>
{
var mongoConfiguration = x.GetRequiredService<IOptions<MongoConfiguration>>().Value;
var settings = MongoClientSettings.FromConnectionString(mongoConfiguration.ConnectionString);
settings.LinqProvider = LinqProvider.V3;
return new MongoClient(settings);
})
.AddSingleton(x =>
{
var client = x.GetRequiredService<IMongoClient>();
var configuration = x.GetRequiredService<IOptions<MongoConfiguration>>().Value;
return client.GetDatabase(configuration.DatabaseName);
})
.AddSingleton(x =>
{
var database = x.GetRequiredService<IMongoDatabase>();
return database.GetCollection<MyCollection>(GetConfigurationValue("MyCollectionName"));
});
|
MongoConfiguration.cs
|
public class MongoConfiguration
{
public string ConnectionString { get; set; } = string.Empty;
public string DatabaseName { get; set; } = string.Empty;
}
|
MongoProvider.cs
|
public class MongoProvider(IMongoCollection<MyCollection> myCollection)
{ }
|
Entity Framework and LINQ
|
using MongoDB.Driver.Linq;
var users = await userCollection
.AsQueryable()
.Where(x => x.FirstName == "Nicolas")
.ToListAsync();
|
 |
Error: IQueryable doesn't implement IDbAsyncEnumerable.
Check you are using MongoDB.Driver.Linq and not System.Data.Entity |
Find
Filter
|
var builder = Builders<MyClass>.Filter;
FilterDefinition<MyClass> filter = builder.Empty;
filter &= builder.Exists(x => x.Property1);
filter &= builder.Eq(x => x.Property1, "value");
filter &= builder.In(x => x.Property1, new[] { "value1", "value2" }); // filter by Property1 equals to one of the values
filter &= builder.AnyIn(x => x.Tags, new[] { "value1", "value2" }); // filter by string[] Tags property which contains at least value1 or value2
filter &= builder.All(x => x.Tags, new[] { "value1", "value2" }); // filter by string[] Tags property which contains at least value1 and value2, order doesn't matter
filter &= builder.ElemMatch(x => x.Items, Builders<Item>.Filter.Eq(i => i.Name, "Item1")); // filter by Items which have a Name equals to "Item1"
var result = await collection
.Find(filter)
.SortByDescending(x => x.Property1)
.Skip(100)
.Limit(10)
.ToListAsync();
var result = (await collection.FindAsync(filter)).ToList();
|
Handle different types
|
// get all the documents
var bsonDocumentCollection = database.GetCollection<BsonDocument>("MyCollection");
var filter = Builders<BsonDocument>.Filter.Empty;
var result = await bsonDocumentCollection.Find(filter).ToListAsync();
// get all the Class1 document
var class1Collection = database.GetCollection<Class1>("MyCollection");
await type1Collection.InsertOneAsync(new Class1 { Name = "Name1" });
var filter = Builders<Class1>.Filter.Eq(x => x.Type, nameof(Class1));
var filter = Builders<SimpleClass>.Filter.Exists(x => x.Name); // get all the documents which have a property Name
var result = await class1Collection.Find(filter).ToListAsync();
class Class1
{
public ObjectId Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Type { get; set; } = nameof(Class1);
}
|
Join
|
record Group(int Id, string Name);
record User(int Id, string Name, int GroupId);
record UserWithGroup(int Id, string Name, int GroupId, Group Group) : User(Id, Name, GroupId);
record GroupWithUsers(int Id, string Name, List<User> Users) : Group(Id, Name);
|
Join
|
var usersWithGroups = await userCollection
.AsQueryable()
.Join(
groupCollection.AsQueryable(),
u => u.GroupId,
g => g.Id,
(u, g) => new UserWithGroup(u.Id, u.Name, u.GroupId, g))
.ToListAsync();
|
GroupJoin
|
var usersWithGroups = await userCollection
.AsQueryable()
.GroupJoin(
groupCollection.AsQueryable(),
u => u.GroupId,
g => g.Id,
(u, g) => new UserWithGroup(u.Id, u.Name, u.GroupId, g.First()))
.ToListAsync();
var groupsWithUsers = await groupCollection
.AsQueryable()
.GroupJoin(
userCollection.AsQueryable(),
g => g.Id,
u => u.GroupId,
(g, u) => new GroupWithUsers(g.Id, g.Name, u.ToList()))
.ToListAsync();
|
Lookup
|
var filter = Builders<UserWithGroups>.Filter.Eq(x => x.GroupId, 1);
var userGroups = await userCollection
.Aggregate()
.Lookup<User, Group, UserWithGroups>(
groupCollection,
u => u.GroupId,
g => g.Id,
uwg => uwg.Groups)
.Match(filter)
.SortByDescending(x => x.Id)
.ToListAsync();
record UserWithGroups(int Id, string Name, int GroupId, Group[] Groups) : User(Id, Name, GroupId);
var filter = Builders<GroupWithUsers>.Filter.ElemMatch(x => x.Users, Builders<User>.Filter.Eq(u => u.Name, "User 2"));
var groupsWithUsers = await groupCollection
.Aggregate()
.Lookup<Group, User, GroupWithUsers>(
userCollection,
g => g.Id,
u => u.GroupId,
gwu => gwu.Users)
.Match(filter)
.SortByDescending(x => x.Id)
.ToListAsync();
|
Pipeline
|
var stages = new BsonDocument[]
{
MatchStage(getTimeSeriesQuery),
ProjectionStage(),
SortStage()
};
var pipeline = PipelineDefinition<InputClass, OutputClass>.Create(stages);
var results = (await myCollection.AggregateAsync(pipeline)).List();
BsonDocument MatchStage(GetTimeSeriesQuery getTimeSeriesQuery)
{
var match = new BsonDocument("property1", "value1");
if (!string.IsNullOrEmpty(variable2))
{
match.AddRange(
new BsonDocument("property2", variable2)
);
}
return new BsonDocument("$match", match);
}
BsonDocument ProjectionStage() =>
new BsonDocument(
"$project",
new BsonDocument
{
{ "_id", 0 },
{ "property1", 1 },
{ "property2", 1 }
}
);
BsonDocument SortStage() =>
new BsonDocument("$sort", new BsonDocument("timestamp", 1));
|
Insert / Update
|
// insert
await itemCollection.InsertOneAsync(item);
await itemCollection.InsertManyAsync([item1, item2]);
FilterDefinition<Item> filter = Builders<Item>.Filter.Eq(nameof(Item.Id), item.Id);
// update
Item updatedItem = await itemCollection.FindOneAndReplaceAsync(filter, item);
// upsert
var options = new FindOneAndReplaceOptions<Item, T> { IsUpsert = true };
await itemCollection.FindOneAndReplaceAsync(filter, item, options);
// patch
UpdateDefinitionBuilder<Item> updateBuilder = Builders<Item>.Update;
UpdateDefinition<Item> updateDefinition = Builders<Item>.Update.Combine(
updateBuilder.Set(nameof(Item.Name), "updatedName"),
updateBuilder.Set(nameof(Item.Available), false));
UpdateResult result = await itemCollection.UpdateOneAsync(filter, updateDefinition);
var success = result.ModifiedCount > 0;
|
|
var mongoUrl = new MongoUrl("MONGODB_CONNECTION_STRING");
var mongoClientSettings = MongoClientSettings.FromUrl(mongoUrl);
mongoClientSettings.ClusterConfigurator = cb =>
{
cb.Subscribe<CommandStartedEvent>(e =>
{
logger.LogTrace($"{e.CommandName} - {e.Command.ToJson()}");
});
};
this.mongoClient = new MongoClient(mongoClientSettings);
|
Configure the Log so it will be displayed in Visual Studio Output Debug window.
Serialize a dictionary with an Enum as key
Error: An error occurred while serializing the Values property of class ...: When using DictionaryRepresentation.Document key values must serialize as strings
|
class MyClass
{
public ObjectId Id { get; set; }
public Dictionary<MyEnum, int> Values { get; set; } = [];
}
// serialize the enum as string
BsonSerializer.RegisterSerializer(new EnumSerializer<MyEnum>(BsonType.String));
|
BsonDocument
|
var bsonDocument = BsonDocument.Parse(jsonDocument.RootElement.GetRawText());
var bsonDocument = myObject.ToBsonDocument();
bsonDocument["fieldName"] = "value";
|
Errors
The provider for the source IQueryable doesn't implement IDbAsyncQueryProvider
Use ToCursorAsync()
|
await (await itemCollection.AsQueryable().ToCursorAsync()).ToListAsync();
|