Reputation: 684
I'm migrating a NodeJs project to NestJs, this project uses MongoDB as back-end database and Mongoose as ODM. I was using the mongoose-sequence plugin to handle autoincrement sequences, however I'm facing troubles requiring the library under NestJs.
The mongoose-sequence documentation explains how to import the library using CommonJS syntax as follows:
const mongoose = require('mongoose')
const AutoIncrementFactory = require('mongoose-sequence');
const connection = await mongoose.createConnection('mongodb://...');
const AutoIncrement = AutoIncrementFactory(connection);
Using ES6 import syntax it would be something like:
import * as mongoose from 'mongoose';
import * as AutoIncrementFactory from 'mongoose-sequence';
const connection = ...;
const AutoIncrement = AutoIncrementFactory(connection);
However since NestJs uses Dependency Injection, accessing the native connection is not so direct. According to the documentation to integrate MongoDB using Mongoose accessing the native Mongoose Connection object can be done using the @InjectConnection()
decorator as follows:
@Injectable()
export class CatsService {
constructor(@InjectConnection() private connection: Connection) {}
}
But since TypeScript decorators can only be attached to a class declaration, method, accessor, property, or parameter I don't see how to inject the connection, require the plugin and initialize it on my Schema classes.
Upvotes: 7
Views: 12386
Reputation: 763
At this time 2023 Sept, mongoose-sequence
does not work with mongoose 7
refer to this issue
it does not work with mongoose 7. Schema.create hangs. seems to be related to callbacks being deprecated.
However there is a new package @typegoose/auto-increment
https://www.npmjs.com/package/@typegoose/auto-increment
npm i @typegoose/auto-increment
import { Module } from '@nestjs/common';
import { MongooseModule, getConnectionToken } from '@nestjs/mongoose';
import { User, UserSchema } from './model/user.model';
import { UsersController } from './controller/users.controller';
import { UsersService } from './service/Users.service';
import {
AutoIncrementID,
AutoIncrementIDOptions,
} from '@typegoose/auto-increment';
@Module({
imports: [
MongooseModule.forFeatureAsync([
{
name: User.name,
useFactory: async () => {
const schema = UserSchema;
schema.plugin(AutoIncrementID, {
field: 'numbering',
startAt: 1,
} satisfies AutoIncrementIDOptions);
return schema;
},
inject: [getConnectionToken()],
},
]),
],
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}
Upvotes: 0
Reputation: 55
I run into this problem and it worked for me from the first time
@Module({
imports: [MongooseModule.forFeatureAsync([
{
name: Supplier.name,
useFactory: async (connection: Connection) =>{
const schema = SupplierSchema;
const AutoIncrement = require('mongoose-sequence')(connection)
schema.plugin(AutoIncrement, {inc_field: 'code'});
return schema;
},
inject: [getConnectionToken(process.env.DATA_BASE_URI)]
}
])],
controllers: [SupplierController],
providers: [SupplierService]
})
but a simple questions : why would i use async when i don't have any await ?
Upvotes: 0
Reputation: 31
I faced the same problem but this worked for me:
MongooseModule.forFeatureAsync([
{
name: Cats.name,
useFactory: async (connection: Connection) => {
const schema = CatsSchema;
const AutoIncrement = require('mongoose-sequence')(connection);
schema.plugin(AutoIncrement, {inc_field: 'id'});
return schema;
},
inject: [getConnectionToken()],
},
]),
Upvotes: 3
Reputation: 684
It's possible to register a plugin for a given schema using the forFeatureAsync()
method of the MongooseModule
along with a factory provider (i.e., useFactory
).
Following the example from the official documentation:
@Module({
imports: [
MongooseModule.forFeatureAsync([
{
name: Cat.name,
useFactory: () => {
const schema = CatsSchema;
schema.plugin(require('mongoose-autopopulate'));
return schema;
},
},
]),
],
})
export class AppModule {}
However with the mongoose-sequence
plugin it's necessary to pass the native Mongoose connection object to the plugin initialization. This can be achieved by injecting the connection into the factory provider with the getConnectionToken
method:
import {getConnectionToken, MongooseModule} from '@nestjs/mongoose';
import * as AutoIncrementFactory from 'mongoose-sequence';
@Module({
imports: [
MongooseModule.forFeatureAsync([
{
name: Cat.name,
useFactory: async (connection: Connection) => {
const schema = CatsSchema;
const AutoIncrement = AutoIncrementFactory(connection);
schema.plugin(AutoIncrement, {inc_field: 'id'});
return schema;
},
inject: [getConnectionToken('YOUR_CONNECTION_NAME')],
},
]),
],
})
export class AppModule {}
Upvotes: 11