Code_Ed_Student
Code_Ed_Student

Reputation: 1190

Paginate Result of related models

This is another follow up to a previous question. There are only two models involved: category and game which share a hasMany relation. Example: The endpoint /Categories/1001/games/mature list all games of fighting category that have mature flag set to true. However, I am unable to paginate the response. What is the proper way to paginate based on the code shown below? I would like to only display 10 results at a time.

common/models/category.js

Category.mature = function(id, callback) {
    var app = this.app;
    var Game = app.models.game;
    Category.findById(id, {}, function(err, category) {
        if (err) return callback(err);
        //Now call the Game find method
        Game.find({
            "where": {
                categoryId: id,
                mature: true
            }
        }, function(err, gameArr) {
            if (err) return callback(err);
            callback(null, gameArr);
        });
    });
}


Category.remoteMethod(
'mature', {
    accepts: [{
        arg: 'id',
        type: 'number',
        required: true
    }],
    // mixing ':id' into the rest url allows $owner to be determined and used for access control
    http: {
        path: '/:id/games/mature',
        verb: 'get'
    },
    returns: {
        arg: 'games',
        type: 'array'
    }
}
);

Tables/Models

catgories

category_name       category_id 
-------------       -----------
fighting            1001
racing              1002
sports              1003

games

game_id         game_name           category_id     mature      description           published_date
-----------     ------------        -----------     -------     -----------           --------------
13KXZ74XL8M     Tekken              10001           true        Published by Namco.     1994
138XZ5LPJgM     Forza               10002           false       Published by Microsoft  2005

API Result:

games [ 
{
gameName: 'Tekken', 
gameInfo : 
[
    { 
        description : 'Published by Namco.',
        published_date : '1994'
    }
],
        categorName: 'fighting', 
        categoryId: 1001, 
        mature: true 
}
.....
]

Upvotes: 0

Views: 371

Answers (1)

notbrain
notbrain

Reputation: 3396

If you are stuck with the code above, you will need to download the full set of Games and then paginate on the frontend. Without being able to send in limit and skip values to your queries, there is no other way.

If you can change this code and add arguments to the remote method, the underlying mysql connector format with the Node API would look like this:

Game.find({
  "where": {
    categoryId: id,
    mature: true
  },
  "limit": 10, // 10 per page
  "skip": 10 // hard coded for page 2, this needs to be passed in
}, function(err, gameArr) {
  if (err) return callback(err);
  callback(null, gameArr);
});

The values for limit and skip should be added to your remote method definition and registration, and then the UI can send in dynamic values based on the page displayed.

The page on the skip filter has an example for pagination as well:

https://docs.strongloop.com/display/public/LB/Skip+filter

If this will be using some sort of UI library like the Angular SDK, you can make the same query at the Controller level using the lb-ng generator script and the models created there. You could also add the pagination values there, no need for a custom remote method.

Update:

To add the skip and limit numbers to your remote method, you need to update your remote method signature, the accepts array would change to

accepts: [
  {
    arg: 'id',
    type: 'number',
    required: true
  },
  {
    arg: 'skip',
    type: 'number',
    required: true
  },
  {
    arg: 'limit',
    type: 'number',
    required: true
  }
]

And then add the same 2 new arguments to the method itself:

Category.mature = function(id, skip, limit, callback) {
  // ...your code...
});

You can call it using query parameters at this point, like ?skip=10&limit=10 just appended to the existing path. Or, you can change the http.path to something like

path: '/:id/games/mature/:skip/:limit'

and then call the resource with /1/games/mature/10/10 to achieve the same result with a parameterized URL.

Upvotes: 2

Related Questions