MongoDB (Mongoose)
Attention Dans cet article, vous apprendrez comment créer unDatabaseModule
basé sur le package Mongoose à partir de zéro en utilisant des composants personnalisés. En conséquence, cette solution contient beaucoup de surcharge que vous pouvez omettre en utilisant le package dédié@nestjs/mongoose
prêt à l'emploi et disponible prêt à l'emploi. Pour en savoir plus, voir ici.
Mongoose est l'outil de modélisation d'objets MongoDB le plus populaire.
Pour commencer#
Pour commencer l'aventure avec cette bibliothèque, nous devons installer toutes les dépendances nécessaires :
$ npm install --save mongoose
La première étape est d'établir une connexion avec notre base de données en utilisant la fonction connect()
. La fonction connect()
retourne une Promise
, et donc nous devons créer un async provider.
import * as mongoose from 'mongoose';
export const databaseProviders = [
{
provide: 'DATABASE_CONNECTION',
useFactory: (): Promise<typeof mongoose> =>
mongoose.connect('mongodb://localhost/nest'),
},
];
import * as mongoose from 'mongoose';
export const databaseProviders = [
{
provide: 'DATABASE_CONNECTION',
useFactory: () => mongoose.connect('mongodb://localhost/nest'),
},
];
Astuce En suivant les meilleures pratiques, nous avons déclaré le fournisseur personnalisé dans le fichier séparé qui a un suffixe *.providers.ts
.
Ensuite, nous devons exporter ces fournisseurs pour les rendre accessibles pour le reste de l'application.
import { Module } from '@nestjs/common';
import { databaseProviders } from './database.providers';
@Module({
providers: [...databaseProviders],
exports: [...databaseProviders],
})
export class DatabaseModule {}
Maintenant nous pouvons injecter l'objet Connection
en utilisant le décorateur @Inject()
. Chaque classe qui dépendrait du fournisseur asynchrone Connection
attendra jusqu'à ce qu'une Promise
soit résolue.
Injection de modèle#
Avec Mongoose, tout est dérivé d'un Schema. Définissons le CatSchema
:
import * as mongoose from 'mongoose';
export const CatSchema = new mongoose.Schema({
name: String,
age: Number,
breed: String,
});
Le CatsSchema
appartient au répertoire cats
. Ce répertoire représente le CatsModule
.
Il est maintenant temps de créer un fournisseur Model :
import { Connection } from 'mongoose';
import { CatSchema } from './schemas/cat.schema';
export const catsProviders = [
{
provide: 'CAT_MODEL',
useFactory: (connection: Connection) => connection.model('Cat', CatSchema),
inject: ['DATABASE_CONNECTION'],
},
];
import { CatSchema } from './schemas/cat.schema';
export const catsProviders = [
{
provide: 'CAT_MODEL',
useFactory: (connection) => connection.model('Cat', CatSchema),
inject: ['DATABASE_CONNECTION'],
},
];
Attention Dans les applications réelles, vous devriez éviter les magic strings. LeCAT_MODEL
et leDATABASE_CONNECTION
doivent être conservés dans le fichierconstants.ts
séparé.
Maintenant nous pouvons injecter le CAT_MODEL
dans le CatsService
en utilisant le décorateur @Inject()
:
import { Model } from 'mongoose';
import { Injectable, Inject } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';
import { CreateCatDto } from './dto/create-cat.dto';
@Injectable()
export class CatsService {
constructor(
@Inject('CAT_MODEL')
private catModel: Model<Cat>,
) {}
async create(createCatDto: CreateCatDto): Promise<Cat> {
const createdCat = new this.catModel(createCatDto);
return createdCat.save();
}
async findAll(): Promise<Cat[]> {
return this.catModel.find().exec();
}
}
import { Injectable, Dependencies } from '@nestjs/common';
@Injectable()
@Dependencies('CAT_MODEL')
export class CatsService {
constructor(catModel) {
this.catModel = catModel;
}
async create(createCatDto) {
const createdCat = new this.catModel(createCatDto);
return createdCat.save();
}
async findAll() {
return this.catModel.find().exec();
}
}
Dans l'exemple ci-dessus, nous avons utilisé l'interface Cat
. Cette interface étend l'interface Document
du package mongoose :
import { Document } from 'mongoose';
export interface Cat extends Document {
readonly name: string;
readonly age: number;
readonly breed: string;
}
La connexion à la base de données est asynchrone, mais Nest rend ce processus complètement invisible pour l'utilisateur final. La classe CatModel
attend la connexion à la base de données, et le CatsService
est retardé jusqu'à ce que le modèle soit prêt à être utilisé. L'application entière peut démarrer lorsque chaque classe est instanciée.
Voici la version finale de CatsModule
:
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
import { catsProviders } from './cats.providers';
import { DatabaseModule } from '../database/database.module';
@Module({
imports: [DatabaseModule],
controllers: [CatsController],
providers: [
CatsService,
...catsProviders,
],
})
export class CatsModule {}
Astuce N'oubliez pas d'importer leCatsModule
dans la racineAppModule
.
Exemple#
Un exemple concret est disponible ici.