rostamiani
rostamiani

Reputation: 3245

How to use `mongoose-delete` plugin with NestJs and typescript?

I'm using Mongoose in NestJs library and want to use mongoose-delete plugin for all of my schemas.

But I don't know how to use it with nestJS And Typescript.

First i installed both mongoose-delete and @Types/mongoose-delete libraries but there is no typescript documentary for This plugin. This is the recommended method for adding plugin by nest:

    MongooseModule.forRoot(MONGO_URI, {
      connectionFactory: connection => {
        connection.plugin(require('mongoose-delete'));
        return connection;
      },
    }),

And absolutely this generates esLint error:

Require statement not part of import statement.eslint

And I cannot use delete function. It's not defined in the mongoose.Dcoument

  export type ChannelDocument = Channel & Document;

  constructor(
    @InjectModel(Channel.name) private _channelModel: Model<ChannelDocument>,
  ) {}

  async delete(id: string) {
    this._channelModel.delete({ id });
    // This is undefined -^
  }

Upvotes: 2

Views: 5152

Answers (4)

buzuo shu
buzuo shu

Reputation: 1

to use SoftDeleteModel

database migrate file

import mongoose, { Connection } from 'mongoose';
import { Cat, CatDocument, CatSchema } from './schema/cat.schema';
import { User, UserDocument, UserSchema } from './schema/user.schema';
import { Org, OrgDocument, OrgSchema } from './schema/org.schema';
import { NestFactory } from '@nestjs/core';
import { getConnectionToken } from '@nestjs/mongoose';
import { MongoModule } from './mongo.module';
import { Role, RoleDocument, RoleSchema } from './schema/role.schema';


import { SoftDeleteModel } from 'mongoose-delete';



const getModels = async () => {
  mongoose.set('strictQuery', true);

  const app = await NestFactory.create(MongoModule);
  const connect = app.get<Connection>(getConnectionToken());
  const catModel = connect.model(
    Cat.name,
    CatSchema,
  ) as unknown as SoftDeleteModel<CatDocument>;
  const orgModel = connect.model(
    Org.name,
    OrgSchema,
  ) as unknown as SoftDeleteModel<OrgDocument>;
  const userModel = connect.model(
    User.name,
    UserSchema,
  ) as unknown as SoftDeleteModel<UserDocument>;
  const roleModel = connect.model(
    Role.name,
    RoleSchema,
  ) as unknown as SoftDeleteModel<RoleDocument>;

  // Return models that will be used in migration methods
  return {
    connect,
    catModel,
    orgModel,
    userModel,
    roleModel,
  };
};

export default getModels;

User Schema

import { Permission, Role } from './role.schema';
import { BaseOrgSchema } from './base-org.schema';
import { Org } from './org.schema';
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';
import mongoose from 'mongoose';
import { toJson } from '.';

@Schema({
  toJSON: toJson,
  timestamps: true,
})
export class User extends BaseOrgSchema {
  /**
   * name
   */
  @Prop({ required: true })
  // @Prop({ required: true, unique: true })
  public name!: string;


  /**
   * password
   */
  @Prop({ required: true, select: false })
  public password!: string;
}

export const UserSchema = SchemaFactory.createForClass(User);
export type UserDocument = HydratedDocument<User>;

controller demo


import { SoftDeleteModel } from 'mongoose-delete';


export class UserController {
  constructor(
    @InjectModel(User.name)
    private readonly model: SoftDeleteModel<UserDocument>,
  ) {}

  @Delete(':id')
  @Describe('delete user')
  async delete(@Param('id') id: string): Promise<void> {
    // no type error
    const res = await this.model.delete(id);
    if (res) {
      return;
    }
    throw new BadRequestException('xxx');
  }
}

db module demo

import { Global, Module } from '@nestjs/common';
import { MongoService } from './mongo.service';
import { MongooseModule } from '@nestjs/mongoose';

@Global()
@Module({
  imports: [
    MongooseModule.forRoot('mongodb://localhost/dbname', {
      connectionFactory: (connection) => {
        // eslint-disable-next-line @typescript-eslint/no-var-requires
        connection.plugin(require('mongoose-delete'), {
          deletedAt: true,
          overrideMethods: true,
          indexFields: true,
        });
        return connection;
      },
      lazyConnection: true,
    }),
  ],
  providers: [MongoService],
  exports: [MongoService],
})
export class MongoModule {}

migrate demo

// Import your models here

import getModels from '@app/mongo/getModels';

export async function up(): Promise<void> {
  const { userModel } = await getModels();
  // if ignore type check run ok, miss type check
  // no type error
  await userModel.delete({});
}

export async function down(): Promise<void> {
  // Write migration here
  const { userModel } = await getModels();
  // if ignore type check run ok, miss type check
  // no type error
  await userModel.restore({});
}

Upvotes: 0

GO-DIE
GO-DIE

Reputation: 11

use soft delete plugin => https://www.npmjs.com/package/soft-delete-mongoose-plugin

A simple and friendly soft delete plugin for Mongoose,implementation using TS. Methods were added and overridden on Mongoose model to realize soft deletion logic.

you can use it as a global plugin:

import { plugin } from 'mongoose';
import { SoftDelete } from 'soft-delete-mongoose-plugin';

// define soft delete field name
const IS_DELETED_FIELD = 'isDeleted';
const DELETED_AT_FIELD = 'deletedAt';

// Use soft delete plugin
plugin(
  new SoftDelete({
    isDeletedField: IS_DELETED_FIELD,
    deletedAtField: DELETED_AT_FIELD,
  }).getPlugin(),
);

// other code
// ... 

Upvotes: 1

Sergio Su&#225;rez
Sergio Su&#225;rez

Reputation: 136

Try to restart you IDE (vscode if you use) after install this package: @types/mongoose-delete

Upvotes: 0

Centaur
Centaur

Reputation: 122

Please take a look at mongoose-softdelete-typescript.

import { Schema, model } from 'mongoose';
import { softDeletePlugin, ISoftDeletedModel, ISoftDeletedDocument } from 'mongoose-softdelete-typescript';

const TestSchema = new Schema({
  name: { type: String, default: '' },
  description: { type: String, default: 'description' },
});

TestSchema.plugin(softDeletePlugin);

const Test = model<ISoftDeletedDocument, ISoftDeletedModel<ISoftDeletedDocument>>('Test', TestSchema);
const test1 = new Test();
// delete single document
const newTest = await test1.softDelete();
// restore single document
const restoredTest = await test1.restore();
// find many deleted documents
const deletedTests = await Test.findDeleted(true);
// soft delete many documents with conditions
await Test.softDelete({ name: 'test' });

// support mongo transaction
const session = await Test.db.startSession();
session.startTransaction();
try {
  const newTest = await test1.softDelete(session);

  await session.commitTransaction();
} catch (e) {
  console.log('e', e);
  await session.abortTransaction();
} finally {
  await session.endSession();
}

Upvotes: -1

Related Questions