npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

easy-mongoose-paginate

v1.2.1

Published

A query and aggregate pagination library for Mongoose with custom labels.

Downloads

70

Readme

Easy Mongoose Paginate

A query and aggregate pagination library for Mongoose with custom labels.

Why This Plugin

Easy-mongoose-paginate is a simple pagination library inspired by mongoose-paginate-v2 with two main improvements:

  1. Paginating both aggregate and find query with one package
  2. Adding a direct style usage in addition to plugin approach -> in progress

The below documentation is not perfect. Feel free to contribute. Having any fun usage of the package, feel free to update this readme

Installation

npm install easy-mongoose-paginate

Usage

Plugin approach

Add paginate plugin to your schema and then use model paginateQuery and paginateAggregate methods:

const mongoose = require('mongoose');
const easyMongoosePaginate = require('easy-mongoose-paginate');

const userSchema = new mongoose.Schema({
  /* your schema definition */
});

userSchema.plugin(easyMongoosePaginate);

const userModel = mongoose.model('user', userSchema);

//Find query
const users = await userModel.paginateQuery({}, { select: "email", limit: 10 })

//Aggregate query
const users = await userModel.paginateAggregate([], { page: 1, limit: 10 }) 

Typescript

Easy-mongoose-paginate ship with it's own type definition. There is no need to install types for it.

import easyMongoosePaginate  from 'easy-mongoose-paginate';
import { EasyPaginateModel } from 'mongoose';

const userSchema = new mongoose.Schema({
  /* your schema definition */
});

userSchema.plugin(easyMongoosePaginate);
interface userDocument extends Document, IUserSchema { }

const userModel = mongoose.model<UserDocument, EasyPaginateModel<UserDocument>>('user', userSchema);

//Find query
const users = await userModel.paginateQuery({}, { select: "email", limit: 10 }) // Usage

//Aggregate query
const users: IPaginationResult<T> = await userModel.paginateAggregate([], { page: 2, limit: 10 }) // Usage

Nest Js usage

Wrap model with EasyPaginateModel. Make sure you have added easy mongoose paginate as a plugin to the model else you will get a type error for EasyPaginateModel.

//model.ts
@Schema({ timestamps: true })
export class Category extends BaseSchema {
  @Prop({ required: true, unique: true })
  name: string;

  @Prop({ trim: true })
  description: string;
}

const CategorySchema = SchemaFactory.createForClass(Category);
CategorySchema.plugin(easyMongoosePaginate);
export { CategorySchema };

//service.ts
import { EasyPaginateModel } from 'mongoose';

@Injectable()
export class CategoryService {
  constructor(
    @InjectModel(Category.name)
    private categoryModel: EasyPaginateModel<Category>,
  ) {}

    public async getAllCategories(query: CommonQuery) {
    const categories = await this.categoryModel.paginateQuery(
      { isDeleted: false },
      query,
    );
    console.log(categories)
    //results
    {
      // result.docs
      // result.totalDocs = 100
      // result.limit = 10
      // result.page = 1
      // result.totalPages = 10
      // result.hasNextPage = true
      // result.nextPage = 2
      // result.hasPrevPage = false
      // result.prevPage = null
      // result.pagingCounter = 1
    };
  }

}

Model.paginateQuery([query], [options])

Returns promise

Parameters

  • [query] {Object} - Query criteria. Documentation

  • [options] {Object}

    • [select] {Object | String} - Fields to return (by default returns all fields). Documentation
    • [collation] {Object} - Specify the collation Documentation
    • [sort] {Object | String} - Sort order. Documentation
    • [populate] {Array | Object | String} - Paths which should be populated with other documents. Documentation
    • [lean=false] {Boolean} - Should return plain javascript objects instead of Mongoose documents? Documentation
    • [page=1] {Number}
    • [limit=10] {Number}, Any number less than 1 will return all documents
    • [labels] {Object} - Developers can provide custom labels for manipulating the response data.
    • [allowDiskUse] {Boolean} - Set this to true, which allows the MongoDB server to use more than 100 MB for query. This option can let you work around QueryExceededMemoryLimitNoDiskUseAllowed errors from the MongoDB server. (Default: False)

Model.paginateAggregate([stage], [options])

Returns promise

Parameters

  • [stage] {Array} - Aggregate pipeline stages. Documentation

  • [options] {Object}

    • [project] {Object | String} - Fields to return (by default returns all fields). Documentation
    • [collation] {Object} - Specify the collation Documentation
    • [sort] {Object | String} - Appends a new $sort operator to this aggregate pipeline. Documentation
    • [page=1] {Number}
    • [lookup] {Object} Add related fields in aggregate Documentation
    • [limit=10] {Number}, Any number less than 1 will return all documents
    • [labels] {Object} - Developers can provide custom labels for manipulating the response data.
    • [allowDiskUse] {Boolean} - Set this to true, which allows the MongoDB server to use more than 100 MB for query. This option can let you work around QueryExceededMemoryLimitNoDiskUseAllowed errors from the MongoDB server. (Default: False)

Return value

Promise fulfilled with object having properties:

  • docs {Array} - Array of documents
  • totalDocs {Number} - Total number of documents in collection that match a query
  • limit {Number} - Limit that was used
  • hasPrevPage {Bool} - Availability of prev page.
  • hasNextPage {Bool} - Availability of next page.
  • page {Number} - Current page number
  • totalPages {Number} - Total number of pages.
  • prevPage {Number} - Previous page number if available or NULL
  • nextPage {Number} - Next page number if available or NULL
  • pagingCounter {Number} - The starting index/serial/chronological number of first document in current page. (Eg: if page=2 and limit=10, then pagingCounter will be 11). Easy mongoose paginate uses a 1-based page index

Please note that the above properties can be renamed by setting labels attribute.

Sample Usage

Return first 10 documents from 100

const options = {
  page: 1,
  limit: 10,
  collation: {
    locale: 'en',
  },
};

const results = await Model.paginateQuery({}, options)

//results
{
  // result.docs
  // result.totalDocs = 100
  // result.limit = 10
  // result.page = 1
  // result.totalPages = 10
  // result.hasNextPage = true
  // result.nextPage = 2
  // result.hasPrevPage = false
  // result.prevPage = null
  // result.pagingCounter = 1
};

With custom return labels

Users can customize the names of the object returned by modifying the labels.

  • totalDocs
  • docs
  • limit
  • page
  • nextPage
  • prevPage
  • hasNextPage
  • hasPrevPage
  • totalPages
  • pagingCounter

You should pass the names of the properties you wish to change using labels object in options. Same query with custom labels

const myCustomLabels = {
  totalDocs: 'itemCount',
  docs: 'itemsList',
  limit: 'perPage',
  page: 'currentPage',
  nextPage: 'next',
  prevPage: 'prev',
  totalPages: 'pageCount',
  pagingCounter: 'slNo',
};

const options = {
  page: 1,
  limit: 10,
  labels: myCustomLabels,
};

const results = await Model.paginateAggregate([], options)

//results
{
  // result.itemsList [here docs become itemsList]
  // result.itemCount = 100 [here totalDocs becomes itemCount]
  // result.perPage = 10 [here limit becomes perPage]
  // result.currentPage = 1 [here page becomes currentPage]
  // result.pageCount = 10 [here totalPages becomes pageCount]
  // result.next = 2 [here nextPage becomes next]
  // result.prev = null [here prevPage becomes prev]
  // result.slNo = 1 [here pagingCounter becomes slNo]
  // result.hasNextPage = true
  // result.hasPrevPage = false
};

Other Examples

Using offset and limit:

const results = await Model.paginateQuery({}, { offset: 30, limit: 10 })

//results
{
  // result.docs
  // result.totalPages
  // result.limit - 10
  // result.offset - 30
};

More advanced example

var query = {};
var options = {
  select: 'title date author',
  sort: { date: -1 },
  populate: 'author',
  lean: true,
  limit: 10,
};
const books = await Book.paginateQuery(query, options)

Zero or negative limit - Get all data

You can use limit=0 to get all the data:

const results = await Model.paginateAggregate([], { limit: 0 })

//results
{
  // result.docs - all data
  // result.totalDocs
  // result.limit - 0
};

Remove labels from the result

Set a label to "false" to remove it from the returned result

const results = await Model.paginateAggregate([], { limit: 0 }, {hasPrevPage: "false",hasNextPage: "false", pagingCounter: "false"})

//results - it does not include those fields.
{
  // result.itemsList [here docs become itemsList]
  // result.itemCount = 100 [here totalDocs becomes itemCount]
  // result.perPage = 10 [here limit becomes perPage]
  // result.currentPage = 1 [here page becomes currentPage]
  // result.pageCount = 10 [here totalPages becomes pageCount]
  // result.next = 2 [here nextPage becomes next]
  // result.prev = null [here prevPage becomes prev]
};

Set global config

To avoid repetition, you can override the default options or set some options globally. For specific query that should be different from the config you set globally. Pass the options to paginateQuery or paginate aggregate to override the global config.

import easyMongoosePaginate, { easyMongoosePaginateConfig } from 'easyMongoosePaginate';

//set options
easyMongoosePaginateConfig.globalOptions = { limit: 1 }

const results = await Model.paginateQuery([], { lean: true })

//results
{
  // result.docs 
  // result.totalDocs
  // result.limit = 1     instead of 10 which is the default
  //...
};

Retrieve all options

Retrieve the current state of all the options the package is currently using. This is useful when you have set global options in a lot of places

import easyMongoosePaginate, { easyMongoosePaginateConfig } from 'easyMongoosePaginate';

const options = easyMongoosePaginateConfig.getOptions()
console.log(options)

//results
{
    // sort: "",
    // limit: 1,
    // page: 1,
    // select: "",
    // populate: "",
    // project: {},
    // allowDiskUse: false,
    // lean: false,
    // ...
};

AllowDiskUse for large datasets

Sets the allowDiskUse option, which allows the MongoDB server to use more than 100 MB for query. This option can let you work around QueryExceededMemoryLimitNoDiskUseAllowed errors from the MongoDB server.

Note that this option requires MongoDB server >= 4.4. Setting this option is a no-op for MongoDB 4.2 and earlier.

const options = {
  limit: 10,
  page: 1,
  allowDiskUse: true,
};

const results = await Model.paginateQuery({}, options)

Below are some references to understand more about preferences,

MIT