0
# Dependency Injection
1
2
Decorators for injecting Mongoose models and connections into NestJS services and controllers. The dependency injection system integrates seamlessly with NestJS's DI container to provide type-safe model and connection injection.
3
4
## Capabilities
5
6
### @InjectModel Decorator
7
8
Injects a Mongoose model into constructor parameters for use in services and controllers.
9
10
```typescript { .api }
11
/**
12
* Parameter decorator that injects a Mongoose model
13
* @param model - Model name to inject
14
* @param connectionName - Optional connection name for multi-database setup
15
* @returns Parameter decorator function
16
*/
17
function InjectModel(model: string, connectionName?: string): ParameterDecorator;
18
```
19
20
**Usage Examples:**
21
22
```typescript
23
import { Injectable } from '@nestjs/common';
24
import { InjectModel } from '@nestjs/mongoose';
25
import { Model } from 'mongoose';
26
import { User } from './schemas/user.schema';
27
28
// Basic model injection
29
@Injectable()
30
export class UserService {
31
constructor(@InjectModel(User.name) private userModel: Model<User>) {}
32
33
async create(createUserDto: any): Promise<User> {
34
const createdUser = new this.userModel(createUserDto);
35
return createdUser.save();
36
}
37
38
async findAll(): Promise<User[]> {
39
return this.userModel.find().exec();
40
}
41
42
async findById(id: string): Promise<User> {
43
return this.userModel.findById(id).exec();
44
}
45
46
async update(id: string, updateUserDto: any): Promise<User> {
47
return this.userModel.findByIdAndUpdate(id, updateUserDto, { new: true }).exec();
48
}
49
50
async delete(id: string): Promise<User> {
51
return this.userModel.findByIdAndDelete(id).exec();
52
}
53
}
54
55
// Multi-database model injection
56
@Injectable()
57
export class UserService {
58
constructor(
59
@InjectModel(User.name, 'users-db') private userModel: Model<User>,
60
@InjectModel(Profile.name, 'profiles-db') private profileModel: Model<Profile>,
61
) {}
62
63
async createUserWithProfile(userData: any, profileData: any): Promise<{ user: User; profile: Profile }> {
64
const user = await new this.userModel(userData).save();
65
const profile = await new this.profileModel({ ...profileData, userId: user._id }).save();
66
return { user, profile };
67
}
68
}
69
70
// Multiple models in single service
71
@Injectable()
72
export class BlogService {
73
constructor(
74
@InjectModel(Post.name) private postModel: Model<Post>,
75
@InjectModel(Comment.name) private commentModel: Model<Comment>,
76
@InjectModel(User.name) private userModel: Model<User>,
77
) {}
78
79
async createPostWithAuthor(postData: any, authorId: string): Promise<Post> {
80
const author = await this.userModel.findById(authorId);
81
if (!author) {
82
throw new Error('Author not found');
83
}
84
85
const post = new this.postModel({ ...postData, author: authorId });
86
return post.save();
87
}
88
89
async addComment(postId: string, commentData: any): Promise<Comment> {
90
const post = await this.postModel.findById(postId);
91
if (!post) {
92
throw new Error('Post not found');
93
}
94
95
const comment = new this.commentModel({ ...commentData, post: postId });
96
return comment.save();
97
}
98
}
99
```
100
101
### @InjectConnection Decorator
102
103
Injects a Mongoose connection instance for advanced database operations and transaction management.
104
105
```typescript { .api }
106
/**
107
* Parameter decorator that injects a Mongoose connection
108
* @param name - Optional connection name for multi-database setup
109
* @returns Parameter decorator function
110
*/
111
function InjectConnection(name?: string): ParameterDecorator;
112
```
113
114
**Usage Examples:**
115
116
```typescript
117
import { Injectable } from '@nestjs/common';
118
import { InjectConnection, InjectModel } from '@nestjs/mongoose';
119
import { Connection, Model } from 'mongoose';
120
import { User } from './schemas/user.schema';
121
import { Order } from './schemas/order.schema';
122
123
// Basic connection injection
124
@Injectable()
125
export class DatabaseService {
126
constructor(@InjectConnection() private connection: Connection) {}
127
128
async getDatabaseStats(): Promise<any> {
129
const stats = await this.connection.db.stats();
130
return {
131
database: this.connection.name,
132
collections: stats.collections,
133
dataSize: stats.dataSize,
134
indexSize: stats.indexSize,
135
};
136
}
137
138
async createIndexes(): Promise<void> {
139
const collections = await this.connection.db.listCollections().toArray();
140
for (const collection of collections) {
141
await this.connection.collection(collection.name).createIndex({ createdAt: -1 });
142
}
143
}
144
}
145
146
// Named connection injection
147
@Injectable()
148
export class MultiDbService {
149
constructor(
150
@InjectConnection('users-db') private usersConnection: Connection,
151
@InjectConnection('orders-db') private ordersConnection: Connection,
152
) {}
153
154
async syncUserData(userId: string): Promise<void> {
155
const session = await this.usersConnection.startSession();
156
try {
157
await session.withTransaction(async () => {
158
// Perform operations within transaction
159
const user = await this.usersConnection.collection('users').findOne({ _id: userId });
160
if (user) {
161
await this.usersConnection.collection('user_cache').replaceOne(
162
{ userId },
163
{ ...user, lastSync: new Date() },
164
{ upsert: true }
165
);
166
}
167
});
168
} finally {
169
await session.endSession();
170
}
171
}
172
}
173
174
// Transaction management with connection and models
175
@Injectable()
176
export class TransactionService {
177
constructor(
178
@InjectConnection() private connection: Connection,
179
@InjectModel(User.name) private userModel: Model<User>,
180
@InjectModel(Order.name) private orderModel: Model<Order>,
181
) {}
182
183
async createUserAndOrder(userData: any, orderData: any): Promise<{ user: User; order: Order }> {
184
const session = await this.connection.startSession();
185
186
try {
187
const result = await session.withTransaction(async () => {
188
// Create user within transaction
189
const user = new this.userModel(userData);
190
await user.save({ session });
191
192
// Create order within same transaction
193
const order = new this.orderModel({ ...orderData, userId: user._id });
194
await order.save({ session });
195
196
return { user, order };
197
});
198
199
return result;
200
} finally {
201
await session.endSession();
202
}
203
}
204
}
205
```
206
207
## Utility Functions
208
209
### getModelToken
210
211
Generates the dependency injection token used for model injection.
212
213
```typescript { .api }
214
/**
215
* Generates dependency injection token for a model
216
* @param model - Model name
217
* @param connectionName - Optional connection name
218
* @returns DI token string
219
*/
220
function getModelToken(model: string, connectionName?: string): string;
221
```
222
223
**Usage Examples:**
224
225
```typescript
226
import { getModelToken } from '@nestjs/mongoose';
227
228
// Get token for default connection
229
const userToken = getModelToken('User');
230
// Returns: 'UserModel'
231
232
// Get token for named connection
233
const userTokenWithConnection = getModelToken('User', 'users-db');
234
// Returns: 'users-db/UserModel'
235
236
// Use in custom providers
237
const providers = [
238
{
239
provide: 'CUSTOM_USER_SERVICE',
240
useFactory: (userModel: Model<User>) => {
241
return new CustomUserService(userModel);
242
},
243
inject: [getModelToken(User.name)],
244
},
245
];
246
```
247
248
### getConnectionToken
249
250
Generates the dependency injection token used for connection injection.
251
252
```typescript { .api }
253
/**
254
* Generates dependency injection token for a connection
255
* @param name - Optional connection name
256
* @returns DI token string
257
*/
258
function getConnectionToken(name?: string): string;
259
```
260
261
**Usage Examples:**
262
263
```typescript
264
import { getConnectionToken } from '@nestjs/mongoose';
265
266
// Get token for default connection
267
const defaultConnectionToken = getConnectionToken();
268
// Returns: 'DatabaseConnection'
269
270
// Get token for named connection
271
const namedConnectionToken = getConnectionToken('users-db');
272
// Returns: 'users-db'
273
274
// Use in custom providers
275
const providers = [
276
{
277
provide: 'DATABASE_HEALTH_CHECK',
278
useFactory: (connection: Connection) => {
279
return new DatabaseHealthCheck(connection);
280
},
281
inject: [getConnectionToken()],
282
},
283
];
284
```
285
286
## Advanced Integration Patterns
287
288
### Custom Providers with Tokens
289
290
```typescript
291
import { Module, Provider } from '@nestjs/common';
292
import { getModelToken, getConnectionToken } from '@nestjs/mongoose';
293
294
const customProviders: Provider[] = [
295
{
296
provide: 'USER_REPOSITORY',
297
useFactory: (userModel: Model<User>) => {
298
return new UserRepository(userModel);
299
},
300
inject: [getModelToken(User.name)],
301
},
302
{
303
provide: 'DATABASE_MANAGER',
304
useFactory: (connection: Connection) => {
305
return new DatabaseManager(connection);
306
},
307
inject: [getConnectionToken()],
308
},
309
];
310
311
@Module({
312
providers: [...customProviders],
313
exports: ['USER_REPOSITORY', 'DATABASE_MANAGER'],
314
})
315
export class CustomModule {}
316
```
317
318
### Testing with Injection Tokens
319
320
```typescript
321
import { Test, TestingModule } from '@nestjs/testing';
322
import { getModelToken } from '@nestjs/mongoose';
323
324
describe('UserService', () => {
325
let service: UserService;
326
let model: Model<User>;
327
328
beforeEach(async () => {
329
const module: TestingModule = await Test.createTestingModule({
330
providers: [
331
UserService,
332
{
333
provide: getModelToken(User.name),
334
useValue: {
335
find: jest.fn(),
336
findById: jest.fn(),
337
create: jest.fn(),
338
save: jest.fn(),
339
},
340
},
341
],
342
}).compile();
343
344
service = module.get<UserService>(UserService);
345
model = module.get<Model<User>>(getModelToken(User.name));
346
});
347
348
it('should find all users', async () => {
349
const users = [{ name: 'Test User' }];
350
jest.spyOn(model, 'find').mockReturnValue({
351
exec: jest.fn().mockResolvedValue(users),
352
} as any);
353
354
const result = await service.findAll();
355
expect(result).toEqual(users);
356
});
357
});
358
```