【问题标题】:Pagination in nodejs with mysql使用 mysql 在 nodejs 中进行分页
【发布时间】:2016-06-12 04:39:38
【问题描述】:

在我的项目中,我需要使用分页查询数据库,并为用户提供基于当前搜索结果进行查询的功能。像限制之类的东西,我找不到任何与nodejs一起使用的东西。我的后端是mysql,我正在写一个rest api。

【问题讨论】:

    标签: mysql sql node.js pagination limit


    【解决方案1】:

    我采用了@Benito的解决方案,并试图使其更清晰

    var numPerPage = 20;
    var skip = (page-1) * numPerPage; 
    var limit = skip + ',' + numPerPage; // Here we compute the LIMIT parameter for MySQL query
    sql.query('SELECT count(*) as numRows FROM users',function (err, rows, fields) {
        if(err) {
            console.log("error: ", err);
            result(err, null);
        }else{
            var numRows = rows[0].numRows;
            var numPages = Math.ceil(numRows / numPerPage);
            sql.query('SELECT * FROM users LIMIT ' + limit,function (err, rows, fields) {
                if(err) {
                    console.log("error: ", err);
                    result(err, null);
                }else{
                    console.log(rows)
                    result(null, rows,numPages);
                }
            });            
        }
    });
    

    【讨论】:

      【解决方案2】:

      您可以尝试类似的方法(假设您使用Express 4.x)。

      使用GET参数(这里page是你想要的页面结果数,npp是每页结果数)。

      在此示例中,查询结果设置在响应负载的results 字段中,而分页元数据设置在pagination 字段中。

      至于是否可以根据当前搜索结果进行查询,您需要稍微扩展一下,因为您的问题有点不清楚。

      var express = require('express');
      var mysql   = require('mysql');
      var Promise = require('bluebird');
      var bodyParser = require('body-parser');
      var app = express();
      
      var connection = mysql.createConnection({
        host     : 'localhost',
        user     : 'myuser',
        password : 'mypassword',
        database : 'wordpress_test'
      });
      var queryAsync = Promise.promisify(connection.query.bind(connection));
      connection.connect();
      
      // do something when app is closing
      // see http://stackoverflow.com/questions/14031763/doing-a-cleanup-action-just-before-node-js-exits
      process.stdin.resume()
      process.on('exit', exitHandler.bind(null, { shutdownDb: true } ));
      
      app.use(bodyParser.urlencoded({ extended: true }));
      
      app.get('/', function (req, res) {
        var numRows;
        var queryPagination;
        var numPerPage = parseInt(req.query.npp, 10) || 1;
        var page = parseInt(req.query.page, 10) || 0;
        var numPages;
        var skip = page * numPerPage;
        // Here we compute the LIMIT parameter for MySQL query
        var limit = skip + ',' + numPerPage;
        queryAsync('SELECT count(*) as numRows FROM wp_posts')
        .then(function(results) {
          numRows = results[0].numRows;
          numPages = Math.ceil(numRows / numPerPage);
          console.log('number of pages:', numPages);
        })
        .then(() => queryAsync('SELECT * FROM wp_posts ORDER BY ID DESC LIMIT ' + limit))
        .then(function(results) {
          var responsePayload = {
            results: results
          };
          if (page < numPages) {
            responsePayload.pagination = {
              current: page,
              perPage: numPerPage,
              previous: page > 0 ? page - 1 : undefined,
              next: page < numPages - 1 ? page + 1 : undefined
            }
          }
          else responsePayload.pagination = {
            err: 'queried page ' + page + ' is >= to maximum page number ' + numPages
          }
          res.json(responsePayload);
        })
        .catch(function(err) {
          console.error(err);
          res.json({ err: err });
        });
      });
      
      app.listen(3000, function () {
        console.log('Example app listening on port 3000!');
      });
      
      function exitHandler(options, err) {
        if (options.shutdownDb) {
          console.log('shutdown mysql connection');
          connection.end();
        }
        if (err) console.log(err.stack);
        if (options.exit) process.exit();
      }
      

      这是此示例的 package.json 文件:

      {
        "name": "stackoverflow-pagination",
        "dependencies": {
          "bluebird": "^3.3.3",
          "body-parser": "^1.15.0",
          "express": "^4.13.4",
          "mysql": "^2.10.2"
        }
      }
      

      【讨论】:

      • 嗨 Benito ,上面的代码有点错误 var limit = skip + ',' + skip + numPerPage;该行没有正确分页。所以现在更新行代码是 var limit = skip + ',' + numPerPage;
      • 您好 Manish,感谢您的有用评论。你说得对,我马上修改我的代码。奇怪的是,我今天查看了这段(旧)代码,那行对我来说似乎有点错误,但我没有花时间修复它!
      【解决方案3】:

      正在寻找快速解决方案。也许对某人有用。

      SELECT id  FROM complexCoding LIMIT ? OFFSET ?
      ",req.query.perpage,((req.query.page-1) * req.query.perpage)
      

      别忘了按照total count of id除以perpage来分页

      【讨论】:

        【解决方案4】:

        我写了一个分页类,以便在不同的页面上使用它,我使用引导程序来设置链接样式,如果你不使用引导程序,你可以更改它。

        物品路线

        router.get('/items/:page',(req,res) => {
        const db = require('mysql'),
                Pagination = require('./pagination'),
        
                // Get current page from url (request parameter)
                page_id = parseInt(req.params.page),
                currentPage = page_id > 0 ? page_id : currentPage,
        
        //Change pageUri to your page url without the 'page' query string 
                pageUri = '/items/';
        
                /*Get total items*/
                db.query('SELECT COUNT(id) as totalCount FROM items',(err,result)=>{
        
                    // Display 10 items per page
                    const perPage = 10,
                        totalCount = result[0].totalCount;
        
                    // Instantiate Pagination class
                    const Paginate = new Pagination(totalCount,currentPage,pageUri,perPage);
        
        
                    /*Query items*/
                    db.query('SELECT * FROM items LIMIT '+Paginate.perPage+' OFFSET '+Paginate.start,(err,result)=>{
        
                        data = {
                            items : result,
                            pages : Paginate.links()
                        }
        
                        // Send data to view
                        res.render('items',data);
                    });
                });
        
        });
        

        在项目视图中,只需打印“页面”即可生成分页链接

        {{ pages }}
        

        pagination.js >> 将此代码添加到 pagination.js 并将其导入您要使用分页的任何页面

        class Pagination{
        
        constructor(totalCount,currentPage,pageUri,perPage=2){
            this.perPage = perPage;
            this.totalCount =parseInt(totalCount);
            this.currentPage = parseInt(currentPage);
            this.previousPage = this.currentPage - 1;
            this.nextPage = this.currentPage + 1;
            this.pageCount = Math.ceil(this.totalCount / this.perPage);
            this.pageUri = pageUri;
            this.offset  = this.currentPage > 1 ? this.previousPage * this.perPage : 0;
            this.sidePages = 4;
            this.pages = false;
        }
        
        
        
        links(){
            this.pages='<ul class="pagination pagination-md">';
        
            if(this.previousPage > 0)
                this.pages+='<li class="page-item"><a class="page-link" href="'+this.pageUri + this.previousPage+'">Previous</a></li>';
        
        
                /*Add back links*/
                if(this.currentPage > 1){
                    for (var x = this.currentPage - this.sidePages; x < this.currentPage; x++) {
                        if(x > 0)
                            this.pages+='<li class="page-item"><a class="page-link" href="'+this.pageUri+x+'">'+x+'</a></li>';
                    }
                }
        
                /*Show current page*/
                this.pages+='<li class="page-item active"><a class="page-link" href="'+this.pageUri+this.currentPage+'">'+this.currentPage+'</a></li>';
        
                /*Add more links*/
                for(x = this.nextPage; x <= this.pageCount; x++){
        
                    this.pages+='<li class="page-item"><a class="page-link" href="'+this.pageUri+x+'">'+x+' </a></li>';
        
                    if(x >= this.currentPage + this.sidePages)
                        break;
                }
        
        
                /*Display next buttton navigation*/
                if(this.currentPage + 1 <= this.pageCount)
                    this.pages+='<li class="page-item"><a class="page-link" href="'+this.pageUri+this.nextPage+'">Next</a></li>';
        
                this.pages+='</ul>';
        
            return this.pages;
        }
        }
        module.exports = Pagination;
        

        【讨论】:

        • 嗨,我知道这是一个线程,但也许有人读过这个。我尝试从@Peter Moses 调整解决方案,但我有点挣扎。 1. 导入失败:“TypeError: db.query is not a function”和 2. 我找不到应该定义 Paginate.start 的位置。我在代码中没有找到它
        • @Miracuru 在尝试使用该功能之前,您是否从 npm 安装了 mysql 包?您也可以使用 mysql2:确保您使用 npm install mysqlnpm install mysql2 npmjs.com/package/mysql2
        • 谢谢@Peter Moses 我已经直接安装了 mysql2 包。我还找到了另一种解决方案。因此,我不再使用此解决方案。我只是使用这个准备好的语句: 并阅读关键:来自 url 的值参数。这使我可以使用导航选项创建前端。
        猜你喜欢
        • 2023-03-20
        • 1970-01-01
        • 2011-10-09
        • 1970-01-01
        • 2013-12-20
        • 2011-07-18
        • 2015-05-16
        • 2012-03-27
        • 1970-01-01
        相关资源
        最近更新 更多