環境
- 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とページ番号です。ページ番号のリンクをクリックすると、そのページの画面を表示するというページネーションボタンを簡単に作成出来るようになっています。