home / skills / stuartf303 / sorcha / mongodb

mongodb skill

/.claude/skills/mongodb

This skill configures MongoDB document and query operations for Sorcha's distributed ledger, enabling storage, indexing, and retrieval across warm and cold

npx playbooks add skill stuartf303/sorcha --skill mongodb

Review the files below or copy the command above to add this skill to your agents.

Files (5)
SKILL.md
3.5 KB
---
name: mongodb
description: |
  Configures MongoDB document storage and query operations for Sorcha's distributed ledger
  Use when: implementing document storage, querying collections, creating indexes, or working with Register/Transaction/Docket data
allowed-tools: Read, Edit, Write, Glob, Grep, Bash, mcp__context7__resolve-library-id, mcp__context7__query-docs
---

# MongoDB Skill

MongoDB is the document store for Sorcha's Register Service, providing storage for registers, transactions, dockets, and system blueprints. The codebase uses a two-tier storage architecture: **warm-tier** (mutable `IDocumentStore<T>`) and **cold-tier** (immutable `IWormStore<T>` for WORM/ledger data).

## Quick Start

### Connection Setup

```csharp
// Program.cs - Register Service
builder.Services.AddSingleton<IMongoClient>(sp =>
{
    var connectionString = builder.Configuration.GetConnectionString("MongoDB") 
        ?? "mongodb://localhost:27017";
    return new MongoClient(connectionString);
});

builder.Services.AddSingleton<IMongoDatabase>(sp =>
{
    var client = sp.GetRequiredService<IMongoClient>();
    return client.GetDatabase("sorcha_register");
});
```

### Repository Registration

```csharp
// Use extension method from Sorcha.Storage.MongoDB
builder.Services.AddMongoClient(builder.Configuration);
builder.Services.AddMongoDatabase("sorcha_register");
builder.Services.AddMongoDocumentStore<Blueprint, string>(
    "blueprints",
    doc => doc.Id,
    doc => doc.Id
);
```

## Key Concepts

| Concept | Usage | Example |
|---------|-------|---------|
| Filter Builders | Type-safe queries | `Builders<T>.Filter.Eq(x => x.Id, id)` |
| Update Builders | Atomic updates | `Builders<T>.Update.Set(x => x.Height, 10)` |
| Composite Indexes | Multi-field queries | `IndexKeys.Ascending(x => x.RegisterId).Ascending(x => x.TxId)` |
| WORM Store | Immutable ledger data | `IWormStore<Transaction, string>` - no updates/deletes |
| Document Store | Mutable documents | `IDocumentStore<Blueprint, string>` - full CRUD |

## Common Patterns

### Filtered Query with Pagination

```csharp
var filter = Builders<TransactionModel>.Filter.And(
    Builders<TransactionModel>.Filter.Eq(t => t.RegisterId, registerId),
    Builders<TransactionModel>.Filter.Gte(t => t.TimeStamp, since)
);

var results = await _collection
    .Find(filter)
    .SortByDescending(t => t.TimeStamp)
    .Skip(page * pageSize)
    .Limit(pageSize)
    .ToListAsync(cancellationToken);
```

### Array Element Query

```csharp
// Find transactions where address is in RecipientsWallets array
var filter = Builders<TransactionModel>.Filter.AnyEq(
    t => t.RecipientsWallets, 
    walletAddress
);
```

## See Also

- [patterns](references/patterns.md)
- [types](references/types.md)
- [modules](references/modules.md)
- [errors](references/errors.md)

## Related Skills

- **dotnet** - Runtime and C# patterns
- **entity-framework** - Alternative ORM (PostgreSQL uses EF)
- **redis** - Caching layer integration
- **docker** - MongoDB container setup
- **xunit** - Integration tests with Testcontainers

## Documentation Resources

> Fetch latest MongoDB C# driver documentation with Context7.

**How to use Context7:**
1. Use `mcp__context7__resolve-library-id` to search for "mongodb c# driver"
2. Query with `mcp__context7__query-docs` using the resolved library ID

**Library ID:** `/mongodb/mongo-csharp-driver`

**Recommended Queries:**
- "filter builder examples CRUD operations"
- "BSON serialization attributes"
- "index creation async"
- "aggregation pipeline C#"

Overview

This skill configures MongoDB document storage and query operations for Sorcha's distributed ledger. It wires MongoDB clients and databases into dependency injection, and provides both mutable document stores and immutable WORM ledger stores for registers, transactions, dockets, and blueprints. Use it to standardise storage patterns, indexes, and type-safe queries across the Register Service.

How this skill works

The skill registers IMongoClient and IMongoDatabase in the host DI and exposes helpers to create IDocumentStore<T> (warm-tier) and IWormStore<T> (cold-tier) collections. It relies on the MongoDB C# driver’s Filter and Update builders for type-safe queries and atomic updates, and supports pagination, array element queries, and composite indexes. WORM stores are treated as append-only; document stores support full CRUD and indexing.

When to use it

  • Implementing persistent storage for registers, transactions, dockets, or system blueprints
  • Creating or registering MongoDB-backed document or WORM collections in startup DI
  • Querying collections with filters, pagination, or array element searches
  • Defining composite indexes to optimise multi-field queries
  • Performing atomic updates with Update builders to avoid race conditions

Best practices

  • Register IMongoClient and IMongoDatabase as singletons in DI to reuse connections efficiently
  • Use IDocumentStore<T> for mutable objects and IWormStore<T> for ledger entries that must be immutable
  • Create composite indexes on fields frequently queried together (e.g., RegisterId + TxId or timestamp)
  • Prefer Builders<T>.Filter and Builders<T>.Update for type-safe queries and atomic updates
  • Paginate results with Skip/Limit and sort by a deterministic field (e.g., TimeStamp) to ensure stable pages
  • Index array fields you query with AnyEq to keep array membership queries performant

Example use cases

  • Store and retrieve transactions for a specific register with time-based pagination
  • Append immutable ledger entries to a WORM store and query by TxId without permitting updates
  • Create a blueprint document store and perform atomic updates to metadata fields
  • Query transactions where a wallet address appears in RecipientsWallets using AnyEq
  • Define compound indexes for fast lookups of register+transaction pairs during reconciliation

FAQ

How do I set up the MongoDB client and database in the service?

Register IMongoClient and IMongoDatabase as singletons in DI. Provide a connection string (e.g., mongodb://localhost:27017) and call GetDatabase with your database name (e.g., sorcha_register).

When should I use a WORM store versus a document store?

Use IWormStore<T> for immutable ledger entries that must never be updated or deleted. Use IDocumentStore<T> for mutable application data that requires CRUD operations.