環境
- Node.js: v4.3.2
- MongoDB: 3.2
- Express.js: 4.13.1
- Bootstrap: 3.3.6(ビューで使用)
準備
express-generatorでひな形を作成し、追加のパッケージをインストールしておきます。MongoDBへのアクセスにはmongooseを使用します。
Expressでページネーションを行うために、express-paginateというパッケージを使用します。また、mongoose-paginateをあわせて使用することで楽にページネーション出来るようになります。
$ express pagination-test
$ cd pagination-test
$ npm i express-paginate mongoose mongoose-paginate --save
モデルの作成
nameというプロパティのみを持つUserモデルを作成します。
var mongoose = require('mongoose');
var mongoosePaginate = require('mongoose-paginate');
var Schema = mongoose.Schema;
var userSchema = new Schema({
name: String
});
userSchema.plugin(mongoosePaginate);
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/test');
var User = mongoose.model('User', userSchema);
module.exports = User;
mongoose-paginateはプラグインとして機能します。ユーザスキーマにこのプラグインを追加しています。
MongoDBにはテストデータを入れておきましょう。ページネーションのテストをするのに、ユーザデータが100件くらいあるといいです。このサイトなどでテストデータを作成すると楽です。
ミドルウェアの追加
アプリケーションにページネーションのためのミドルウェアを追加します。
...
// この2行を追加します。
var paginate = require('express-paginate');
app.use(paginate.middleware(10, 50));
// ルーティングの前に追加します。
app.use('/', routes);
app.use('/users', users);
...
ミドルウェアの書式は以下のようになっています。
paginate.middleware(limit, maxLimit)
-
limit: 1ページに含めるドキュメント(アイテム)数のデフォルト値 -
maxLimit: アプリケーションのクライアントが指定できるlimitの最大値
もう少しわかりやすく説明すると、ブラウザで以下のように指定したとします。
http://localhost/?page=1&limit=10
limit=10は、表示されるユーザ数です。limitの指定がなかった場合、上記のデフォルト値(ここでは10)になります。
また、maxLimitが50に設定されていた場合、ブラウザでlimit=100と指定しても、表示されるのは50ユーザまでです。
コントローラ
以下のようにします。
var express = require('express');
var router = express.Router();
var User = require('../user');
var paginate = require('express-paginate');
router.get('/', function(req, res, next) {
User.paginate({}, {page: req.query.page, limit: req.query.limit}, function(err, result) {
res.render('index', {
users: result.docs,
currentPage: result.page,
pageCount: result.pages,
pages: paginate.getArrayPages(req)(3, result.pages, req.query.page)
});
});
});
module.exports = router;
mongoose-paginateプラグインにより、Userモデルはpaginateメソッドを使用できます。第一引数にクエリ、第二引数にはページネーションのためのオプションを渡しています。
ブラウザで以下のように指定したとすると、
http://localhost/?page=2&limit=10
MongoDBから11〜20番目のユーザを取得します。
コールバック関数に渡されるresultには、取得したドキュメント以外の情報も格納されています。
-
result.docs: 取得したドキュメントの配列 -
result.page: 指定したページ番号 -
result.pages: 総ページ数
他にもresult.total(総ドキュメント数)などがあります。詳しくはGithubページへ。
paginate.getArrayPagesは、各ページのURLとページ番号を格納したオブジェクト配列を返します。ビューでページネーションボタンを作成するのに使います。
ビュー
最後にビューの設定を行います。ページネーションボタンの作成に、Bootstrapを使用しています。
extends layout
block content
h1 Users
ul.list-unstyled
each user in users
li= user.name
if paginate.hasPreviousPages || paginate.hasNextPages(pageCount)
ul.pagination
if paginate.hasPreviousPages
li
a(href=paginate.href(true))
span «
if pages
each page in pages
li(class=(currentPage === page.number) ? 'active' : '')
a(href=page.url)= page.number
if paginate.hasNextPages(pageCount)
li
a(href=paginate.href())
span »
ビューではpaginate.hasPreviousPagesとpaginate.hasNextPagesが使用できます。それぞれ、前のページ、後のページが存在するとき、trueを返します。
paginate.href(true)は、前のページを表示するURLを返します。例えば、現在表示しているのが
http://localhost/?page=2&limit=10
であったとき、paginate.href(true)は
http://localhost/?page=1&limit=10
を返します。paginate.href()は後のページを表示するURLを返します。
page.urlおよびpage.numberは、それぞれのページのURLとページ番号です。ページ番号のリンクをクリックすると、そのページの画面を表示するというページネーションボタンを簡単に作成出来るようになっています。
