使用 mysql 在 nodejs 中分页
Pagination in nodejs with mysql
在我的项目中,我需要使用分页查询数据库,并为用户提供基于当前搜索结果进行查询的功能。像限制之类的东西,我找不到任何可以与 nodejs 一起使用的东西。我的后端是 mysql,我正在写一个休息 api。
您可以尝试类似的操作(假设您使用 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
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": "Whosebug-pagination",
"dependencies": {
"bluebird": "^3.3.3",
"body-parser": "^1.15.0",
"express": "^4.13.4",
"mysql": "^2.10.2"
}
}
我写了一个分页 class 为了在不同的页面上使用它,我使用 bootstrap 来设置链接的样式,如果你不使用 bootstrap 可以更改它.
物品路线
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" 即可生成分页链接
{{ 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;
正在寻找快速解决方案。也许对某人有用。
SELECT id FROM complexCoding LIMIT ? OFFSET ?
",req.query.perpage,((req.query.page-1) * req.query.perpage)
不要忘记按照total count of id
除以perpage
分页
我采用了@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);
}
});
}
});
在我的项目中,我需要使用分页查询数据库,并为用户提供基于当前搜索结果进行查询的功能。像限制之类的东西,我找不到任何可以与 nodejs 一起使用的东西。我的后端是 mysql,我正在写一个休息 api。
您可以尝试类似的操作(假设您使用 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
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": "Whosebug-pagination",
"dependencies": {
"bluebird": "^3.3.3",
"body-parser": "^1.15.0",
"express": "^4.13.4",
"mysql": "^2.10.2"
}
}
我写了一个分页 class 为了在不同的页面上使用它,我使用 bootstrap 来设置链接的样式,如果你不使用 bootstrap 可以更改它.
物品路线
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" 即可生成分页链接
{{ 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;
正在寻找快速解决方案。也许对某人有用。
SELECT id FROM complexCoding LIMIT ? OFFSET ?
",req.query.perpage,((req.query.page-1) * req.query.perpage)
不要忘记按照total count of id
除以perpage
我采用了@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);
}
});
}
});