|
2 | 2 | layout: default |
3 | 3 | title: MongoDB |
4 | 4 | parent: Integration |
5 | | -nav_order: 2 |
| 5 | +nav_order: 3 |
6 | 6 | --- |
7 | 7 |
|
8 | | -Mongo DB |
9 | | -======== |
| 8 | +# MongoDB |
10 | 9 |
|
11 | | -To setup EventFlow Mongo DB, install the NuGet package `EventFlow.MongoDB` and add this to your EventFlow setup. |
| 10 | +Use the `EventFlow.MongoDB` integration when you want EventFlow to persist events, |
| 11 | +read models, or snapshots in MongoDB. This guide walks through the recommended |
| 12 | +package, configuration patterns, collection preparation, and a few |
| 13 | +troubleshooting tips. |
| 14 | + |
| 15 | +## Prerequisites |
| 16 | + |
| 17 | +- A MongoDB server (Replica Set recommended for production). EventFlow works with |
| 18 | + MongoDB 5.0 or newer; the integration tests run against Mongo2Go, which ships |
| 19 | + with MongoDB 6.x. |
| 20 | +- A .NET application already wired with `EventFlow`. |
| 21 | +- Network access and credentials that allow reads and writes to the target database. |
| 22 | + |
| 23 | +## Install the NuGet package |
| 24 | + |
| 25 | +Add the MongoDB integration to every project that configures EventFlow. |
| 26 | + |
| 27 | +```bash |
| 28 | +dotnet add package EventFlow.MongoDB |
| 29 | +``` |
| 30 | + |
| 31 | +## Configure EventFlow |
| 32 | + |
| 33 | +The `ConfigureMongoDb` helpers make sure a single `IMongoDatabase` instance is |
| 34 | +registered with DI. You can pass a connection string, a custom `MongoClient`, or |
| 35 | +an `IMongoDatabase` factory. |
| 36 | + |
| 37 | +```csharp |
| 38 | +// Program.cs / Startup.cs |
| 39 | +var mongoUrl = new MongoUrl(Configuration.GetConnectionString("eventflow-mongo")); |
| 40 | +var mongoClient = new MongoClient(mongoUrl); |
| 41 | + |
| 42 | +services.AddEventFlow(ef => ef |
| 43 | + .ConfigureMongoDb(mongoClient, mongoUrl.DatabaseName) |
| 44 | + .UseMongoDbEventStore() // Events |
| 45 | + .UseMongoDbSnapshotStore() // Snapshots (optional) |
| 46 | + .UseMongoDbReadModel<UserReadModel>() // Read models |
| 47 | + .UseMongoDbReadModel<UserNicknameReadModel, UserNicknameLocator>()); |
| 48 | +``` |
| 49 | + |
| 50 | +### Read models must implement `IMongoDbReadModel` |
| 51 | + |
| 52 | +Mongo-backed read models use optimistic concurrency on a `Version` field and |
| 53 | +store documents in a single collection per read model type. Implement the |
| 54 | +interface and optionally override the collection name. |
| 55 | + |
| 56 | +```csharp |
| 57 | +[MongoDbCollectionName("users")] |
| 58 | +public class UserReadModel : IMongoDbReadModel, |
| 59 | + IAmReadModelFor<UserAggregate, UserId, UserCreated> |
| 60 | +{ |
| 61 | + public string Id { get; set; } = default!; // MongoDB document _id |
| 62 | + public long? Version { get; set; } |
| 63 | + public string Username { get; set; } = default!; |
| 64 | + |
| 65 | + public Task ApplyAsync( |
| 66 | + IReadModelContext context, |
| 67 | + IDomainEvent<UserAggregate, UserId, UserCreated> domainEvent, |
| 68 | + CancellationToken cancellationToken) |
| 69 | + { |
| 70 | + Id = domainEvent.AggregateIdentity.Value; |
| 71 | + Username = domainEvent.AggregateEvent.Username.Value; |
| 72 | + return Task.CompletedTask; |
| 73 | + } |
| 74 | +} |
| 75 | +``` |
| 76 | + |
| 77 | +If you omit `MongoDbCollectionNameAttribute`, EventFlow defaults to |
| 78 | +`ReadModel-[TypeName]` for the collection name. |
| 79 | + |
| 80 | +### Snapshots |
| 81 | + |
| 82 | +Calling `UseMongoDbSnapshotStore()` stores aggregate snapshots in the same |
| 83 | +database. Each snapshot is kept in a shared `eventflow-snapshots` collection, |
| 84 | +including the version number and metadata required for upgrades. |
| 85 | + |
| 86 | +## Prepare collections and indexes |
| 87 | + |
| 88 | +EventFlow registers an `IMongoDbEventPersistenceInitializer` that sets up the |
| 89 | +unique index on `(AggregateId, AggregateSequenceNumber)` in the events |
| 90 | +collection. Run it once during application startup or as a migration step. |
12 | 91 |
|
13 | 92 | ```csharp |
14 | | -// ... |
15 | | -.ConfigureMongoDb(client, "database-name") |
16 | | -// ... |
| 93 | +using (var scope = services.BuildServiceProvider().CreateScope()) |
| 94 | +{ |
| 95 | + scope.ServiceProvider |
| 96 | + .GetRequiredService<IMongoDbEventPersistenceInitializer>() |
| 97 | + .Initialize(); |
| 98 | +} |
| 99 | +``` |
| 100 | + |
| 101 | +Read model collections are created lazily. When running in production, pre-create |
| 102 | +them with the appropriate indexes for your query workload (for example, on |
| 103 | +`Username` or `TenantId` fields) and size any capped collections ahead of time. |
| 104 | + |
| 105 | +## Local development quickstart |
| 106 | + |
| 107 | +Spin up a disposable MongoDB container and point your connection string at |
| 108 | +`mongodb://localhost:27017/eventflow`. |
| 109 | + |
| 110 | +```bash |
| 111 | +docker run --rm -p 27017:27017 --name eventflow-mongo mongo:7 |
17 | 112 | ``` |
18 | 113 |
|
19 | | -After setting up Mongo DB support in EventFlow, you can continue to configure it. |
| 114 | +Integration tests live in `Source/EventFlow.MongoDB.Tests` if you need sample |
| 115 | +fixtures for seeding data or running smoke tests. |
| 116 | + |
| 117 | +## Troubleshooting |
| 118 | + |
| 119 | +- **Duplicate key errors on event writes** – ensure the initializer created the |
| 120 | + index or rerun `Initialize()`. Unique index collisions usually indicate a |
| 121 | + concurrency issue in the aggregate. |
| 122 | +- **Read model updates never land** – confirm your read models implement |
| 123 | + `IMongoDbReadModel` and expose a writable `Version` property. Without it, the |
| 124 | + optimistic concurrency check fails silently. |
| 125 | +- **Connection spikes on cold start** – reuse a singleton `MongoClient` instead |
| 126 | + of recreating it per request so the driver can manage pooling. |
| 127 | +- **Changing collection names** – rename carefully and migrate existing data; |
| 128 | + EventFlow does not perform collection migrations automatically. |
| 129 | + |
| 130 | +## See also |
| 131 | + |
| 132 | +- [Event stores](event-stores.md#mongo-db) |
| 133 | +- [Read model stores](read-stores.md#mongo-db) |
| 134 | +- [Snapshots](../additional/snapshots.md) |
20 | 135 |
|
21 | | -- [Event store](event-stores.md#mongo-db) |
22 | | -- [Read model store](read-stores.md#mongo-db) |
|
0 commit comments