Giter VIP home page Giter VIP logo

mongoose-paginate's Introduction

mongoose-paginate

Pagination plugin for Mongoose

NPM version Build status

Note: This plugin will only work with Node.js >= 4.2 and Mongoose >= 4.2

NPM

Installation

npm install mongoose-paginate

Usage

Add plugin to a schema and then use model paginate method:

var mongoose = require('mongoose');
var mongoosePaginate = require('mongoose-paginate');

var schema = new mongoose.Schema({ /* schema definition */ });
schema.plugin(mongoosePaginate);

var Model = mongoose.model('Model',  schema); // Model.paginate()

Model.paginate([query], [options], [callback])

Parameters

  • [query] {Object} - Query criteria. Documentation
  • [options] {Object}
    • [select] {Object | String} - Fields to return (by default returns all fields). 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
    • [leanWithId=true] {Boolean} - If lean and leanWithId are true, adds id field with string representation of _id to every document
    • [offset=0] {Number} - Use offset or page to set skip position
    • [page=1] {Number}
    • [limit=10] {Number}
  • [callback(err, result)] - If specified the callback is called once pagination results are retrieved or when an error has occurred

Return value

Promise fulfilled with object having properties:

  • docs {Array} - Array of documents
  • total {Number} - Total number of documents in collection that match a query
  • limit {Number} - Limit that was used
  • [page] {Number} - Only if specified or default page/offset values were used
  • [pages] {Number} - Only if page specified or default page/offset values were used
  • [offset] {Number} - Only if specified or default page/offset values were used

Examples

Skip 20 documents and return 10 documents

Model.paginate({}, { page: 3, limit: 10 }, function(err, result) {
  // result.docs
  // result.total
  // result.limit - 10
  // result.page - 3
  // result.pages
});

Or you can do the same with offset and limit:

Model.paginate({}, { offset: 20, limit: 10 }, function(err, result) {
  // result.docs
  // result.total
  // result.limit - 10
  // result.offset - 20
});

With promise:

Model.paginate({}, { offset: 20, limit: 10 }).then(function(result) {
  // ...
});

More advanced example

var query = {};
var options = {
  select: 'title date author',
  sort: { date: -1 },
  populate: 'author',
  lean: true,
  offset: 20, 
  limit: 10
};

Book.paginate(query, options).then(function(result) {
  // ...
});

Zero limit

You can use limit=0 to get only metadata:

Model.paginate({}, { offset: 100, limit: 0 }).then(function(result) {
  // result.docs - empty array
  // result.total
  // result.limit - 0
  // result.offset - 100
});

Set custom default options for all queries

config.js:

var mongoosePaginate = require('mongoose-paginate');

mongoosePaginate.paginate.options = { 
  lean:  true,
  limit: 20
};

controller.js:

Model.paginate().then(function(result) {
  // result.docs - array of plain javascript objects
  // result.limit - 20
});

Tests

npm install
npm test

License

MIT

mongoose-paginate's People

Contributors

admsev avatar aegyed91 avatar anggiaj avatar bitdeli-chef avatar cbou avatar connected-dalmer avatar daniel-almer avatar danilodeveloper avatar edwardhotchkiss avatar gimenete avatar giuliano84 avatar jokero avatar matthewrayfield avatar niftylettuce avatar shime avatar t-yamo avatar wix-codeoasis avatar yolapop avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mongoose-paginate's Issues

Error Handling for query

Does this code handle errors ? will
Model.paginate().then(function(result) {
// result.docs - array of plain javascript objects
// result.limit - 20
})
.catch(funciton(err){
// Handle error
})

work ?

Select fields in populated documents

var Link = new Schema({
user : {type: Schema.ObjectId, ref: 'User'},
campaign : {type: Schema.ObjectId, ref: 'Campaign'},
});

var Campaign = new Schema({
title: String,
description : String,
});

Link.paginate(where, {
populate: 'campaign'
}, function(err, links) {
callback(null, links);
});

How to select only 'title' field in populated 'campaign' documents ?

Is this plugin scalable?

I found this answer on stackoverflow:

http://stackoverflow.com/questions/5539955/how-to-paginate-with-mongoose-in-node-js

The cursor.skip() method is often expensive because it requires the server to walk from the beginning of the collection or index to get the offset or skip position before beginning to return result. As offset (e.g. pageNumber above) increases, cursor.skip() will become slower and more CPU intensive. With larger collections, cursor.skip() may become IO bound.

But I see in code is used skip() , so is this scalable?

Searching with Weights

I am trying to apply the following query to the paginate function, but don't think it works.

var docItems = require('../models/docItems.js');
docItems.find(
        {$text: {$search: req.query.searchString}}
        , {score: {$meta: "textScore"}}
    )
        .sort({ score : { $meta : 'textScore' } })
        .exec(function(err, results) {

            return next(err, results);
        });

the , {score: {$meta: "textScore"}} line is what is missing in the following code:

docItems.paginate(
    {$text: {$search: req.query.searchString}, score: {$meta: "textScore"}},
    { page: 1, sortBy: { score : { $meta : 'textScore' } }},
    function(err, results, pageCount, itemCount) {
        console.log('hello');
        return next(err, results, pageCount, itemCount);
    });

Is there a way to submit the score meta line? what am i missing?

Thank you.

3.1.6 from 3.1.3

shouldnt that have been a breaking change? all my paginate implementations didnt work anymore when i updated, i downgraded to 3.1.3 and everything was fine, i thought when the last number changes that there would be no breaking change of the api.

How to change pagination response object

Hi.

How would you go about extending the plugin to change the response structure. Would like to add links e.g hasNext, hasPrevious and rename the fields such as docs to results without having to create an additional middleware

Would be great if someone can point me to the right direction.

Does page enumeration start at 1!?

Feeding 0 as a page number yields no docs but any page number above 1 will ( as long as there are docs for that page ). Is this a bug or intended feature?

how to define what keys I need to return?

When I'm using mongoose, I can find and return the keys I need, just like: myModel.find(null,{name:true})
and the data come back will be[ {_id:xxx,name:xxx}�,{_id:yyy,name:yyy}] ……just like that.
can mongoose-paginate also return specific keys I need?

Using .skip() method being unscalable.

I've been reading the Mongo documentation about the skip() method you're using in your class and it clearly says :

"The cursor.skip() method is often expensive because it requires the server to walk from the beginning of the collection or index to get the offset or skip position before beginning to return result. As offset (e.g. pageNumber above) increases, cursor.skip() will become slower and more CPU intensive. With larger collections, cursor.skip() may become IO bound."

Did you experience any issues with paginating large data-sets? If so, maybe it would be the right time to try a new method for paginating ?

Thank you
Shai

MongoError: Failed to parse 'limit' field must be numeric

Kind of "straight forward" that 'limit' field must be numeric, but in scenario that I got limit from req.query.limit in Express it brings in some, in my opinion, unnecessary "string to number conversion code".

In version 4 everything worked also if limit was string. Not realy a bug, but maybe you can bring this string conversion back in mongoose-paginate core?

Callback should be always last argument

Hi!

There is convention in node.js, that callback is always the last argument of function. Current implementation of mongoose-paginate does not follow this convention and cause conflicts for example with Bluebird. Even though the options might not be used in all situations, i would always appreciate the conventions so it does not cause uncertainty with developers. It is possible to take length of passed arguments and deduce if there is options passed or not.

Paginate method is called on Model, Not Schema.

The README Guide is confusing, Sine :

MySchema.plugin(paginate);
console.log(MySchema.paginate);    //undefined
MyModel = mongoose.model('MyModel', MySchema);
console.log(MyModel.paginate);       //This will work.

Has anyone ever tried using regex?

It doesn't work

I'm using version 3.1.3

with critera {name: { $regex: new RegExp("^" + name.toLowerCase()) }}, mongoose-paginate returns empty result whereas mongoose returns 1 document.

Extend mongoose query class?

I'm having an issue where I sometimes want to paginate, and sometimes I want to find all. It becomes cumbersome because I have to specify population, select, etc in two different formats.

if(iWantToPaginate) {
  return myModel.paginate(query, { populate: 'foo', select: 'bar' });
else {
  return myModel.find(query).populate('foo').select('bar')
}

How simple would it be to have the populate method extend the mongoose query prototype:

myModel.find(query).populate('foo').select('bar').paginate({ page: 4 })

?

Possibly of note: Automattic/mongoose#2696

Rename sortBy to sort

Chased a bug for an hour, then I realised that this library has a different name for sort (sortBy) than I'm used to from mongoose (sort).

In order to prevent backward incompatibility with older paginate versions, you could make sortBy an alias for sort that will additionally throw a deprecation warning in the console.

If it's ok with you, I could implement this myself.

exclude field

How exclude field with this plugin?
I want to exclude fields salt and hashedPassword
User.find(query,'-salt -hashedPassword',function.............

No paginate method on my Model class

Hi,

Regarding to the closed "No paginate method on my Model class" issue at #9, I found the problem that the mongoose module (current version 3.8.8) initializes new object (var mongoose = module.exports = exports = new Mongoose), so if we use :
var mongoose = require('mongoose')
, paginate = require('mongoose-paginate');
then the 1st mongoose variable is different from the mongoose variable with extend paginate method inside the mongoose-paginate module.
That why the error "No paginate method" thrown out.

So I suggest we export the mongoose variable at the bottom of the mongoose-paginate.js:
module.exports = mongoose;

Then we use it as:
var mongoose = require('mongoose-paginate');

Thanks,
Luan Nguyen

Server side error...

I'm using [email protected] and I'm getting the server side error. I'm not sure why it's occurring...

/node_modules/mongoose-paginate/lib/mongoose-paginate.js:55
    callback(null, data.results, Math.ceil(data.count / resultsPerPage) || 1,
    ^
TypeError: object is not a function
    at .../node_modules/mongoose-paginate/lib/mongoose-paginate.js:55:5
    at .../node_modules/mongoose-paginate/node_modules/async/lib/async.js:682:13
    at .../node_modules/mongoose-paginate/node_modules/async/lib/async.js:49:16
    at done (.../node_modules/mongoose-paginate/node_modules/async/lib/async.js:239:19)
    at .../node_modules/mongoose-paginate/node_modules/async/lib/async.js:40:16
    at Promise.<anonymous> (.../node_modules/mongoose-paginate/node_modules/async/lib/async.js:679:17)
    at Promise.<anonymous> (.../node_modules/mongoose/node_modules/mpromise/lib/promise.js:177:8)
    at Promise.emit (events.js:107:17)
    at Promise.emit (...node_modules/mongoose/node_modules/mpromise/lib/promise.js:84:38)
    at Promise.fulfill (.../node_modules/mongoose/node_modules/mpromise/lib/promise.js:97:20)
    at Promise.resolve (.../node_modules/mongoose/lib/promise.js:114:23)
    at Promise.<anonymous> (...node_modules/mongoose/node_modules/mpromise/lib/promise.js:177:8)
    at Promise.emit (events.js:107:17)
    at Promise.emit (.../node_modules/mongoose/node_modules/mpromise/lib/promise.js:84:38)
    at Promise.fulfill (.../node_modules/mongoose/node_modules/mpromise/lib/promise.js:97:20)
    at .../node_modules/mongoose/lib/query.js:1058:26

Query with reference

Hi,

when I do the following:

Group.paginate({destination_country: "some-country-id-1234"}) ...

I get no results back, even though there should be some. Using {} as query gives me all Groups, so the rest of the paginate-function is okay.

Group is a model with destination_country as a reference to the Country Model (which also works fine with all my other needs).

Mongo query error

After reinstall node_modules i am facing this error with our plugin. MongoError: Can't canonicalize query: BadValue bad skip value in query. Mongoose version is 4.4.14, node version is 5.11.0, mongoose-paginate version is latest on npm. I am just using empty object for query, and page and limit for options. {},{page: 0, limit:3}

options

prompt, both at the level of settings, I can change a property docs on list?

get all results

hi, maybe it's a strange request:
how can I get all results using this module?
Basically a value for offset and limit I can be sure I get all results.

Thinking about it it's a pretty basic usage.
Otherwise I have to check the existence of those fields in query string and if they are not set I have to do a plain mongoose find().

populate broken in 3.1.4

Version 3.1.4 breaks populate definitions that use objects, e.g.

[{path: user, select: 'firstname lastname'}, {path: address, select: 'street'}]

Does this work with geospatial queries?

Hey there,

Thank you for the awesome work here.

My application heavily depends on mongoose's geoNear() function to query for nearby places. Does your plugin mongoose-paginate have any support for that geospatial query function?

Thanks in advanced

Sorting

Not sure if this is an issue, but i've tried using this module with sorting as an option, but can't get it to work.

I'm not sure if thats because thats not possible with mongoose-paginate, or if i'm just making some mistakes.

Will there be a typings file?

Hi,

I'm using your component, but I would like to use it a little bit more typesave.
I'm using typescript: Is there some typedefintion out there for mongoose-paginate(official/inofficial) or are you planning to provide one .d.ts-File?

Thanks!

Paginate doesn't work within model

I use paginate within my statics methods of the schema

list: function list( options = {} ) {
    // some preparation ...
    return this.paginate( newOptions.query, newOptions.paginate );
  },

(I prefer to have model's functionality within models and not controllers)
I await on the promise once executed with await (within controller / tests).

But I get:

TypeError: this.paginate is not a function

All my other statics function can be called with this.

Am I missing something? Thanks!

docs sample code syntax error

{ columns: 'title', { populate: 'some_ref' }, sortBy : { title : -1 } });
// must be
{ columns: 'title', { populate: 'some_ref' }, {sortBy : { title : -1 } });

Duplicated 'data.results' argument on the callback

On version 3.1.5, the data.results is passed twice on the callback.

The line:

callback(null, data.results, Math.ceil(data.count / resultsPerPage) || 1, data.results, data.count);

should be:

callback(null, data.results, Math.ceil(data.count / resultsPerPage) || 1, data.count);

Aggregation Support?

It would be neat if aggregations would be supported as well.

However, API-wise I'm not sure if that would mean an additional method or just another option, where the actual query would either be ignored or interpreted as an aggregation pipeline.

Thoughts?

No paginate method on my Model class

I must be doing something wrong because I don't have a .paginate() method on my Models. The following test case demonstrates the problem:

var mongoose = require('mongoose')
  , paginate = require('mongoose-paginate');

var BlogSchema = new mongoose.Schema({
  id    : mongoose.Schema.ObjectId,
  title : String,
  entry : String,
  date  : Date
});

var BlogEntry = mongoose.model('BlogEntry', BlogSchema);
console.log(BlogEntry.paginate); //=> outputs undefined

Is the documentation correct?

I have a problem using the advanced example.

{ columns: 'title', { populate: 'some_ref' }, { sortBy : { title : -1 } }}

What kind of object is this?
Shouldn't this be

{ columns: 'title', populate: 'some_ref' , sortBy : { title : -1 } }

Populate with SELCT

Hello all,
is this capability already built? because I am able use POPULATE along with the PAGINATE but SELECT within the POPULATE is not working.

Thanks!

Sorting/Searching populated documents as well as paginate

I have an Item collection which shows details about the items gets updated very frequently with different prices.

I also have an InventoryItem collection which represents a real item which references then Item collection. It will have its assetId, who owns it, which bot its in etc.

Now I am making a store which I will stock all these InventoryItems in.

Here is the Schemas for Item and InventoryItem:

Item Schema:

var ItemSchema = new mongoose.Schema({
    item: {
        marketName: String,
        model: String,
        set: String,
        exterior: String
    },
    price: {
        currency: String,
        custom: Number,
        steam: Number
    },
    quantity: Number,
    blacklist: {
        type: Boolean,
        default: false
    },
    custom: Boolean,
    iconUrl: String
});

InventoryItem Schema:

var InventoryItemSchema = new mongoose.Schema({
    item: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Item'
    },
    assetId: String,
    location: String,
    bot: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Bot'
    },
    user: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    }
});

Now the problem arises when I try and search InventoryItem by name, or sort by price, because name and price is inside the Item collection.

I can't copy price from an Item into InventoryItem because as I said, the price updates frequently, and there will be multiple of the same Item.

Population is a solution, but I would need to sort/find after populating, which I do not believe is possible.

The store will have potentially thousands of items, so the data needs to be paginated. I am using mongoose-paginate to deal with that.

How would I do this? I am very stumped.

Deprecated

When an project go under deprecated, there are reason which is a bit better then yours. Is there any other project that will continue this one?

Support Mongoose 3.8.0

Hello,

I have an issue with the use of mongoose 3.8.0 because mongoose-paginate use mongoose 3.5.1. So, paginate function is added to 3.5.1 version and not 3.8.

Do you understand the problem ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.