Reputation: 151
Im trying to use mongoose paginate to paginate through an array of values.
class subNotes {
@Prop()
Note: string;
@Prop()
Date: Date;
}
@Schema()
class Travel extends Document {
@Prop()
Country: string;
@Prop()
Recommendation: string;
@Prop()
Level: number;
@Prop()
LevelDescr: string;
@Prop()
Date: Date;
@Prop()
Notes: [subNotes];
}
export const TravelSchema = SchemaFactory.createForClass(Travel); TravelSchema.plugin(mongoosePaginate); So subnotes are updated weekly and will have lots of information that i would like to paginate on service sice. For that im providing apage and limit like arguments in my controllers
async createSlugs(
@Query('page') page = 1,
@Query('limit') limit = 10,
@Param('country') country: string,
) {
limit = limit > 100 ? 100 : limit;
return await this.travelService.getTravelInfo(
{
limit: Number(limit),
page: Number(page),
},
country,
);
}
}
And on the service im injecting my document as a Paginate Model and trying to implement the service like this:
async getTravelInfo(page = 1, limit = 10, country: string) {
await this.saveTravelInfo(country);
const options = {
page: Number(page),
limit: Number(limit),
};
return await this.notesModel.paginate({ Country: country }, options);
}
Yet the paginate isnt doing anything, the entire country data gets selected. Any tip?
async getTravelInfo(page = 1, limit = 10, country: string) {
await this.saveTravelInfo(country);
const options = {
populate: 'subNotes',
page: Number(page),
limit: Number(limit),
};
console.log(options);
return await this.notesModel.paginate({ Country: country }, options);
}
So limit is basically duplicating whats inside my subnotes. If i put Limit 1, returns everything aka 200 documents. If i put Limit 2, returns 400 documents. :|
Upvotes: 4
Views: 13321
Reputation: 426
Here are steps to use mongoose-paginate-v2
in Nest JS...
Here I am taking example of Category module...
category.module.ts
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { CmsAuthModule } from './cms-auth.module';
import { CmsAuthService } from '../../service/cms-auth.service';
import { CategoryService } from 'src/service/category.service';
import { CategoryController } from 'src/controllers/cms/category.controller';
import { Category, CategorySchema } from 'src/entities/category.entity';
@Module({
imports: [
MongooseModule.forFeature([
{ name: Category.name, schema: CategorySchema },
]),
CmsAuthModule,
],
controllers: [CategoryController],
providers: [CategoryService, CmsAuthService],
})
export class CategoryModule {
// constructor() {
// mongoose.plugin(mongoosePaginate);
// }
}
Use import { PaginateModel } from 'mongoose'
in instead of import { Model } from 'mongoose'
in category.service.ts
import { ConflictException, Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { StatusCodes } from 'http-status-codes';
import { PaginateModel } from 'mongoose';
import { CATEGORY_CONFIG } from 'src/config/constants';
import { MESSAGE } from 'src/config/message';
import { CreateCategoryDto, UpdateCategoryDto } from 'src/dtos/category.dto';
import { Category, CategoryDocument } from 'src/entities/category.entity';
@Injectable()
export class CategoryService {
constructor(
@InjectModel(Category.name)
private categoryModal: PaginateModel<CategoryDocument>,
) {}
async findAll() {
const query = {
status: CATEGORY_CONFIG.STATUS_TYPE.ACTIVE,
};
const options = {
select: ['name'],
};
const resData = await this.categoryModal.paginate(query, options);
return {
statusCode: StatusCodes.OK,
message: MESSAGE.SUCCESS.CATEGORY_FETCH_SUCCESS,
data: resData,
};
}
}
Here is the entity file for the same... Use CategorySchema.plugin(mongoosePaginate);
in this file so it will give functionality available in mongoosePaginate.
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';
import * as mongoosePaginate from 'mongoose-paginate-v2';
export type CategoryDocument = HydratedDocument<Category>;
@Schema({ timestamps: true })
export class Category {
@Prop({ required: true, type: String })
name: string;
@Prop({ required: true, type: String })
status: string;
}
export const CategorySchema = SchemaFactory.createForClass(Category);
CategorySchema.plugin(mongoosePaginate);
Upvotes: 1
Reputation: 41
so check this out I made this package to make the implementation of keyset pagination in nestjs with mongoose simple 🙂
https://www.npmjs.com/package/nestjs-keyset-paginator
Upvotes: 4
Reputation: 295
You can implement this using the mongoose-paginate-plugin.
A possible starting point;
import { Inject, Injectable } from '@nestjs/common';
import {
Connection, Document, PaginateModel, Schema,
} from 'mongoose';
import { InjectConnection } from '@nestjs/mongoose';
import TravelSchema from './travel.schema';
interface IRunAnything extends Document{
[key: string]: any;
}
type SampleModel<T extends Document> = PaginateModel<T>;
@Injectable()
export default class ProfileRepository {
constructor(
@InjectConnection() private connection: Connection
) {}
/**
* Run the query.
* The query are just your filters.
*
* @param query
* @param offset
* @param limit
*/
async getTravelInfo(query: object, offset = 10, limit = 10) {
const dynamicModel: SampleModel<IRunAnything> = this.connection.model<IRunAnything>('Travel', this.schema) as SampleModel<IRunAnything>;
const customLabels = {
docs: 'nodes',
page: 'currentPage',
totalPages: 'pageCount',
limit: 'perPage',
totalDocs: 'itemCount',
};
return dynamicModel.paginate(query, { customLabels, offset, limit });
}
}
The solution is a bit hackish but you can build on it and adapt to your use case.
Remember to add the plugin to your schema.
npm i mongoose-paginate-v2
...
import * as mongoosePaginate from 'mongoose-paginate-v2';
TravelSchema.plugin(mongoosePaginate)
...
Upvotes: 2