Node.js API with express& mysql - 获取记录计数,页码,...&提供分页

时间:2018-02-23 09:41:54

标签: javascript mysql sql node.js express

我想得到并提供响应中的total_record_count,page_number,page_size,total_pages,has_more信息,并且能够对结果进行分页,因为我将查询限制为100.最好的方法是什么?

这是我目前的设置:

router.get('/?', function(req, res, next) {
    const sql = "SELECT * from users ";
    const existingParams = ["title", "active"].filter(field => req.query[field]);

    if (existingParams.length) {
        sql += " WHERE ";
        sql += existingParams.map(field => `${field} = ?`).join(" AND ");
        sql += " LIMIT 100 ";
    }

    connection.query(
        sql,
        existingParams.map(field => req.query[field]),
        function (error, results, fields) {
            res.json({"status": 200, "error": null, "total_record_count": 604, "page_number": 1, "page_size": 100, "total_pages": 7, "has_more": true, "records": results});
        }
    );
});

在url中,如果total_record_count超过LIMIT,我希望能够提供/允许页面参数'p'。因此查询参数p指定要返回的页面,从1开始。如果省略p参数,则默认值为1. Sth like:

http://localhost:4001/api/v1/users/?active=0&title=mr&p=1

2 个答案:

答案 0 :(得分:1)

MySQL LIMIT需要2个值,offset&行数。操作这些就是你当然可以做分页的方法。

例如。如果说每页有10个记录长。 第1页= LIMIT 0, 10 第2页= LIMIT 10, 10 第3页= LIMIT 20, 10等。

IOW:LIMIT (pageNo - 1) * PageSize, PageSize

现在使用限制的一个问题是recordcount用于结果集,IOW:有限的10条记录。

但是你可以做的是要求MySQL存储如果未应用LIMIT,记录计数将会是多少。您可以通过在SQL前面添加SQL_CALC_FOUND_ROWS来检索它。

例如。 SELECT SQL_CALC_FOUND_ROWS * FROM TABLE WHERE something LIMIT 10, 10

然后,您可以执行另一个检索此值的查询。

SELECT FOUND_ROWS();

答案 1 :(得分:1)

对于分页,您需要在MySQL中查询类似下面的查询

SELECT * FROM users LIMIT 0,10

使用两个参数,第一个参数指定要返回的第一行的偏移量,第二个参数指定要返回的最大行数。初始行的偏移量为0(不是1)。

您希望将默认值设为第1页和100结果

router.get('/?', function(req, res, next) {
    const sql = "SELECT * from users ";
    const existingParams = ["title", "active"].filter(field => req.query[field]);
    const pageNum = req.query.p || 1;
    const pageSize = req.query.p_size || 100;


    if (existingParams.length) {
        sql += " WHERE ";
        sql += existingParams.map(field => `${field} = ?`).join(" AND ");
    }
    sql += ` LIMIT  ${(pageNum - 1) * PageSize},${PageSize}`;
    ...
});

对于关于提供总行数的第二个问题,您需要为此运行两个查询。您可以在mysql> 4.0中使用SQL_CALC_FOUND_ROWS and FOUND_ROWS()。但是当我们在查询中为WHERE / ORDER子句提供适当的索引时,使用两个单独的查询而不是SQL_CALC_FOUND_ROWS的查询要快得多(一个用于数据,一个用于获取所有行数)。

现在你必须同时运行两个查询以提高性能,所以使用回调你可以利用我为并行运行回调而编写的this function并等到所有回调都完成。或者你可以在这里使用promisified MySQL库,或者你可以使用Bluebird使你的当前库得到宣传。

像这样:

const connection = mysql.createConnection({.....});
global.db  = Bluebird.promisifyAll(connection);
db.queryAsync("SELECT * FROM users")
.then(function(rows){ 
    console.log(rows);
})

然后像这样运行查询

Promise.all([
    db.queryAsync("SELECT * FROM users WHERE title='ridham' LIMIT 0,10"), // generated by your code
    db.queryAsync("SELECT COUNT(*) FROM users WHERE title='ridham'")
]).then(([data, count]) => {
        // your logic to send response
})

或者您也可以运行以下查询,也可以运行

SELECT * FROM 'table' JOIN (SELECT COUNT(*) FROM 'table') t2 WHERE title='ridham' LIMIT 0,10")

此外,您可以使用SequilizeWaterline之类的ORM。这至少会使你对MYSQL更容易10倍。

作为sequilize的例子:

User.findAndCountAll({
    where: {
        title: {
          [Op.like]: 'ridham'
        }
    },
    offset: 10,
    limit: 2
})
.then(result => {
    console.log(result.count);
    console.log(result.rows);
});