A MongoDB repository pattern implementation with TypeScript
npm install mongo-patternsA flexible and type-safe MongoDB repository pattern implementation for TypeScript applications. This package provides a robust abstraction layer for MongoDB operations with a powerful criteria builder for querying and mutation builder for updates.
- ๐ฏ Type-safe MongoDB operations
- ๐ Powerful criteria builder for complex queries
- ๐ Flexible mutation builder for updates and upserts
- ๐ฆ Connection management for multiple databases
- ๐ ๏ธ Repository pattern implementation
- โก Optimized for performance
- ๐งช Well tested with unit and integration tests
- ๐ Support for transaction-like operations
- ๐จ Clean and maintainable code structure
``bash`
npm install mongo-patterns
`typescript
import { MongoDBRepository, Criteria, Mutation, MongoDBConnectionManager } from 'mongo-patterns';
// Define your entity type
interface User {
id: string;
name: string;
email: string;
age: number;
}
// Create your repository
class UserRepository extends MongoDBRepository
constructor(db: Db) {
super(db, 'users');
}
}
// Connect to MongoDB
const db = await MongoDBConnectionManager.connect({
uri: 'mongodb://localhost:27017',
dbName: 'myapp'
});
// Initialize repository
const userRepo = new UserRepository(db);
// Create a user
const user = await userRepo.create({
id:"1",
name: 'John Doe',
email: 'john@example.com',
age: 30
});
// Find users using criteria
const users = await userRepo.findMany(
Criteria.create
.where('age', 'GREATER_THAN', 25)
.andWhere('name', 'LIKE', 'John')
.orderBy('name', 'ASC')
.take(10)
.skip(0)
);
`
The Criteria Builder provides a fluent interface for building complex queries:
`typescript`
const criteria = Criteria.create
.where('age', 'GREATER_THAN', 18)
.andWhere('status', 'IN', ['active', 'pending'])
.orderBy('createdAt', 'DESC')
.take(10)
.skip(0);
Available operators:
- EQUALGREATER_THAN
- LESS_THAN
- GREATER_THAN_OR_EQUAL
- LESS_THAN_OR_EQUAL
- NOT_EQUAL
- IN
- NOT_IN
- LIKE
- BETWEEN
-
The Mutation Builder provides a powerful interface for building update operations:
`typescript
// Simple update
const updateMutation = Mutation.update
.set('name', 'John Doe')
.increment('age', 1)
.push('tags', 'new-tag');
// Upsert operation
const upsertMutation = Mutation.upsert
.set('email', 'john@example.com')
.set('status', 'active');
// Array operations
const arrayMutation = Mutation.update
.push('roles', ['admin'], { $position: 0 })
.addToSet('permissions', ['read', 'write'])
.pull('removedRoles', 'guest');
`
Available mutation operators:
- SET - Set a field valueUNSET
- - Remove a fieldINCREMENT
- - Increment a numeric fieldMULTIPLY
- - Multiply a numeric fieldPUSH
- - Add elements to an arrayPULL
- - Remove elements from an arrayADD_TO_SET
- - Add unique elements to an arrayPOP
- - Remove first or last element from an arrayMIN
- - Update if new value is less than currentMAX
- - Update if new value is greater than currentCURRENT_DATE
- - Set field to current dateRENAME
- - Rename a field
Array modifiers for PUSH operations:
- $each - Add multiple elements$position
- - Insert at specific position$slice
- - Limit array size after operation$sort
- - Sort array after operation
The package includes a robust connection management system:
`typescript
// Connect to multiple databases
const db1 = await MongoDBConnectionManager.connect({
uri: 'mongodb://localhost:27017',
dbName: 'db1'
}, 'client1');
const db2 = await MongoDBConnectionManager.connect({
uri: 'mongodb://localhost:27017',
dbName: 'db2'
}, 'client2');
// Get database instances
const db1Instance = MongoDBConnectionManager.getDb('client1');
const db2Instance = MongoDBConnectionManager.getDb('client2');
// Disconnect
await MongoDBConnectionManager.disconnect('client1');
await MongoDBConnectionManager.disconnectAll();
`
The repository pattern provides standard CRUD operations:
`typescript
// Create
const created = await repo.create(document);
const manyCreated = await repo.createMany([doc1, doc2]);
// Read
const one = await repo.findOne(criteria);
const many = await repo.findMany(criteria);
// Update with Mutation Builder
const updateMutation = Mutation.update
.set('status', 'active')
.increment('loginCount', 1);
const updated = await repo.updateOne(criteria, updateMutation);
// Upsert with Mutation Builder
const upsertMutation = Mutation.upsert
.set('email', 'john@example.com')
.set('createdAt', new Date());
const upserted = await repo.updateOne(criteria, upsertMutation);
// Delete
const deleted = await repo.deleteOne(criteria);
const deletedMany = await repo.deleteMany(criteria);
// Check existence
const exists = await repo.exists(criteria);
`
``
.
โโโ src/
โ โโโ core/ # Core functionality
โ โโโ domain/ # Domain interfaces
โ โโโ infrastructure/ # Implementation
โ โ โโโ mongodb/
โ โโโ types/ # Type definitions
โโโ tests/
โ โโโ integration/ # Integration tests
โ โโโ unit/ # Unit tests
`bashInstall dependencies
npm install
Configuration
The package supports various MongoDB connection options:
`typescript
interface MongoDBConfig {
uri: string;
dbName: string;
options?: {
maxPoolSize?: number;
minPoolSize?: number;
retryWrites?: boolean;
connectTimeoutMS?: number;
socketTimeoutMS?: number;
ssl?: boolean;
replicaSet?: string;
authSource?: string;
};
}
`Development
`bash
Build the project
npm run buildRun tests
npm test`MongoDB Transactions
The library provides robust transaction support through the
MongoDBTransactionManager class, which implements advanced retry strategies and error handling for MongoDB transactions.$3
- Parallel and Sequential transaction execution strategies
- Exponential backoff retry mechanism
- Automatic handling of transient errors and deadlocks
- Configurable transaction options
- Support for mixed operation types within transactions
$3
`typescript
const transactionManager = new MongoDBTransactionManager(client, db);// Execute multiple operations in a transaction
const result = await transactionManager.executeTransaction([
(session) => repository.create(entity1, { session }),
(session) => repository.updateOne(criteria, mutation, session),
(session) => repository.deleteOne(criteria, { session })
]);
if (result.success) {
console.log('Transaction completed successfully');
} else {
console.error('Transaction failed:', result.error);
}
`$3
`typescript
const customTransactionManager = new MongoDBTransactionManager(client, db, {
maxRetries: 3,
initialRetryDelay: 100,
maxRetryDelay: 1000,
readPreference: 'primary',
readConcern: 'snapshot',
writeConcern: {
w: 'majority',
j: true,
wtimeout: 5000
}
});
`$3
1. Handling Concurrent Updates
`typescript
const result = await transactionManager.executeTransaction([
(session) => repository.updateOne(
Criteria.create().where('name', 'EQUAL', 'example'),
Mutation.update().set('value', newValue),
session
)
]);
`2. Multiple Operations Across Collections
`typescript
const result = await transactionManager.executeTransaction([
(session) => repository1.create(entity1, { session }),
(session) => repository2.create(entity2, { session }),
(session) => repository1.updateOne(criteria, mutation, session)
]);
`3. Handling Deadlocks
The transaction manager automatically handles deadlocks by retrying in sequential mode:
`typescript
const result = await transactionManager.executeTransaction([
(session) => repository.create(entity1, { session }),
(session) => repository.updateOne(criteria, mutation, session)
]);// If a deadlock occurs, the transaction will:
// 1. Retry in sequential mode
// 2. Apply exponential backoff
// 3. Return success/failure status with retry information
`$3
The transaction manager provides detailed error information:
`typescript
const result = await transactionManager.executeTransaction([/.../]);console.log({
success: result.success,
executionMode: result.executionMode, // 'parallel' or 'sequential'
retries: result.retries, // number of retry attempts
error: result.error // error details if failed
});
``1. Keep transactions as short as possible
2. Avoid mixing read and write operations when possible
3. Use appropriate read/write concerns for your use case
4. Handle transaction results appropriately
5. Monitor retry counts and execution modes for optimization