使用 node-mysql 和 ExpressJS 在一个请求中执行两个或多个查询

Posted

技术标签:

【中文标题】使用 node-mysql 和 ExpressJS 在一个请求中执行两个或多个查询【英文标题】:Perform two or more queries in one request using node-mysql and ExpressJS 【发布时间】:2015-06-20 06:52:56 【问题描述】:

tl;dr:使用带有 ExpressJS 的 node-mysql 处理对 MySQL 数据库的两个或多个异步查询的正确方法是什么?

我使用 ExpressJS 和 node-mysql 在 MySQL 数据库上执行两个独立的、不相关的数据库查询。由于响应是异步的,因此我嵌套了查询,这意味着它们最终会一个接一个地发生。

这似乎是一种丑陋、缓慢且通常不好的方法,尤其是在我要添加第三个或第四个查询时。

var mysql      = require('mysql');
var credentials = ...

router.get('/api/url/', function (req, res) 
    return_data = 
    var connection = mysql.createConnection(credentials);
    query1 = "SELECT column1 FROM table1 WHERE column2 = 'foo'";
    query2 = "SELECT column1 FROM table2 WHERE column2 = 'bar'";
    connection.query(query1, , function(err, results) 
        return_data.table1 = results;
        connection.query(query2, , function(err, results) 
            return_data.table2 = results;
            connection.end();
            res.send(return_data);
        );
    );
);

【问题讨论】:

【参考方案1】:

来自this article:

为了安全起见,默认情况下,执行多个语句查询是禁用的。要使用多个语句查询,您应该首先在创建连接时启用它,如下所示。

var connection =  mysql.createConnection(  multipleStatements: true  );

启用后,您可以在 connection.query 中执行多个语句查询,如下所示。

connection.query('select column1; select column2; select column3;',    
function(err, result)
  if(err)
      throw err;
  else
      console.log(result[0]);       // Column1 as a result
      console.log(result[1]);       // Column2 as a result
      console.log(result[2]);       // Column3 as a result
  
);

【讨论】:

【参考方案2】:

请记住,为了让查询并行运行,您必须利用连接池。在 mysql 连接上一次只能运行一个查询。有关示例,请参阅https://github.com/felixge/node-mysql/#pooling-connections。

Remyp 的回答需要修改如下:

var mysql      = require('mysql');
var async      = require('async');
var credentials = connectionLimit: 10,...

router.get('/api/url/', function (req, res) 
    var pool = mysql.createPool(credentials);
    var query1 = "SELECT column1 FROM table1 WHERE column2 = 'foo'";
    var query2 = "SELECT column1 FROM table2 WHERE column2 = 'bar'";

    var return_data = ;

    async.parallel([
       function(parallel_done) 
           pool.query(query1, , function(err, results) 
               if (err) return parallel_done(err);
               return_data.table1 = results;
               parallel_done();
           );
       ,
       function(parallel_done) 
           pool.query(query2, , function(err, results) 
               if (err) return parallel_done(err);
               return_data.table2 = results;
               parallel_done();
           );
       
    ], function(err) 
         if (err) console.log(err);
         pool.end();
         res.send(return_data);
    );
);

我会对他的帖子发表评论,但我没有代表这样做,因此发布为答案。

【讨论】:

什么是 parallel_done 在这种情况下作为回调执行?【参考方案3】:

这是使用async 的理想选择。这是您可以使用它重构它的一种方法:

var mysql      = require('mysql');
var async      = require('async');
var credentials = ...

router.get('/api/url/', function (req, res) 
    var connection = mysql.createConnection(credentials);
    var query1 = "SELECT column1 FROM table1 WHERE column2 = 'foo'";
    var query2 = "SELECT column1 FROM table2 WHERE column2 = 'bar'";

    var return_data = ;

    async.parallel([
       function(parallel_done) 
           connection.query(query1, , function(err, results) 
               if (err) return parallel_done(err);
               return_data.table1 = results;
               parallel_done();
           );
       ,
       function(parallel_done) 
           connection.query(query2, , function(err, results) 
               if (err) return parallel_done(err);
               return_data.table2 = results;
               parallel_done();
           );
       
    ], function(err) 
         if (err) console.log(err);
         connection.end();
         res.send(return_data);
    );
);

显然有更优雅的方法可以做到这一点,但这很好地展示了这些概念。这两个查询是并行完成的,一旦它们都完成,我们调用最后一个函数来关闭连接并返回数据。

如果出现错误,我们会立即跳转到最后一个函数并调用它,这可能会导致我们在发送 return_data 时出现奇怪的行为,因此我不建议按原样使用此代码。

如果您想了解更多信息,请查看async documentation。

【讨论】:

以上是关于使用 node-mysql 和 ExpressJS 在一个请求中执行两个或多个查询的主要内容,如果未能解决你的问题,请参考以下文章

在 node-mysql 中使用 SSH 隧道连接到 MySQL

node-mysql 连接池

node-mysql使用

node-mysql 在查询中使用数组

Nodejs学习笔记--- 与MySQL交互(felixge/node-mysql)

将 Q 与 Node-Mysql 一起使用