19
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Express.jsとMongoDBでページネーションする

Posted at

Kobito.dU2yiW.png

環境

  • 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モデルを作成します。

user.js
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件くらいあるといいです。このサイトなどでテストデータを作成すると楽です。

ミドルウェアの追加

アプリケーションにページネーションのためのミドルウェアを追加します。

app.js
...
// この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ユーザまでです。

コントローラ

以下のようにします。

routes/index.js
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を使用しています。

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

19
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?