2016-08-08 6 views
8

node.js restifyモジュールを使用しています。私はjsonで単一のMySQLクエリの結果を出力するREST APIを持っています。 APIのコードは次のとおりです。REST APIで2つのクエリの出力を結合します

var rest_api_get_list = function (app, url_name) { 
    function respond(req, res, next) { 
     var door_mac = req.query.door_mac; 

     var connection = own_mysql.getMySQL_connection(); 

     var query_str = 
       "SELECT doors.mac_addr, " + 
       "sensors.sensor_type " + 
       "FROM sensors " + 
       "WHERE (doors.mac_addr = ?) " 
      ; 

     var query_var = [door_mac]; 

     var query = connection.query(query_str, query_var, function (err, rows, fields) { 
      //if (err) throw err; 
      if (err) { 
       //throw err; 
       console.log(err); 
       logger.info(err); 
      } 
      else { 
       res.send(rows); 
      } 
     }); 
     return next(); 
    } 

    app.get(url_name, respond); 
}; 

次のような別のクエリがあるとします。

var query_str_2 = 
      "SELECT knobs.mac_addr, " + 
      "furniture.furniture_type " + 
      "FROM furnitures" + 
      "WHERE (knobs.mac_addr = ?) " 
     ; 

私は2 MySQLはquery_strquery_str_2を照会の出力を組み合わせて、REST APIがJSONで結果を返すようにしたいです。これはどうすればできますか?

もっと明確にするために、私はこのようなことをするコードを考えています。

var rest_api_get_list = function (app, url_name) { 
    function respond(req, res, next) { 
     var door_mac = req.query.door_mac; 

     var connection = own_mysql.getMySQL_connection(); 

     var query_str = 
       "SELECT doors.mac_addr, " + 
       "sensors.sensor_type " + 
       "FROM sensors " + 
       "WHERE (doors.mac_addr = ?) " 
      ; 

     var query_var = [door_mac]; 

     var query = connection.query(query_str, query_var, function (err, rows_output_1, fields) { 
      //if (err) throw err; 
     }); 

     var query_str_2 = 
      "SELECT knobs.mac_addr, " + 
      "furniture.furniture_type " + 
      "FROM furnitures" + 
      "WHERE (knobs.mac_addr = ?) " 
     ; 

     var query_2 = connection.query(query_str_2, query_var, function (err, rows_output_2, fields) { 
      //if (err) throw err; 

     }); 

     //How to display json output of rows_output_1 and rows_output_2? 

     return next(); 
    } 

    app.get(url_name, respond); 
}; 

EDIT:私はPromisesを使用する回答を引き付けるために賞金を始めました。

+1

あなたは2つのクエリを実行する方法を尋ねていますか、またはSQLの質問に実際に結合を行う方法について質問していますか? – HeadCode

+0

ヘッドコード、申し訳ありませんが明確ではありません。これはSQLの質問ではありません。 2つのクエリを実行し、2つのクエリの結合結果をjsonで返す方法を尋ねています。私はそれをより明確にするために質問を編集しました。ありがとうございました。 –

+1

この問題の難しい部分は、node.jsの非同期性です。問合せは順番に実行できません。この質問に答えるために、ブルーバードのような約束やモジュールがどのように使われているのか興味深いでしょう。 – user781486

答えて

6

asyncのような非同期制御フローを管理するモジュールがこれを手助けすることができます。例えば

function respond(req, res, next) { 

    var door_mac = req.query.door_mac; 
    var connection = own_mysql.getMySQL_connection(); 
    var query_var = [door_mac]; 

    async.parallel([ 
     function (callback) { 

      var query_str = 
       "SELECT doors.mac_addr, " + 
       "sensors.sensor_type " + 
       "FROM sensors " + 
       "WHERE (doors.mac_addr = ?) " 
      ; 
      connection.query(query_str, query_var, callback); 
     }, 
     function (callback) { 

      var query_str_2 = 
       "SELECT knobs.mac_addr, " + 
       "furniture.furniture_type " + 
       "FROM furnitures" + 
       "WHERE (knobs.mac_addr = ?) " 
      ; 
      connection.query(query_str_2, query_var, callback); 
     } 
    ], function (error, results) { 

     // results[0] => result for query_str 
     // results[1] => result for query_str_2 
     // ... return next() or whatever 
    })  
} 
+0

ありがとうございます。 Upvoted。私はそれを試してみる。あなたは、ソリューションが約束を使う方法やブルーバードモジュールのようなものを知っていますか? –

+1

あなたの質問のコードにはコールバックベースのAPIが含まれていたので、私の答えはそれを考慮に入れました。はい、あなたは約束を使うことができますが、コールバックベースのAPIを約束通りのAPIに変換するには、bluebird [promisify](http://bluebirdjs.com/docs/api/promise.promisify.html)のようなものを使う必要があります。ベースのAPIです。約束を返すAPIを取得したら、[Promise.all](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all)結果。 – cartant

+0

ありがとうございます。あなたのソリューションは、コールバックと非同期を使用すると、元のコードはコールバックベースのAPIが関係していたので、一番最初になると思います。 –

3

あなたは@cartantが言うように、あなたは非同期または(より良い)約束(Promise.all(p1, p2).then(...))を使用することができ、並列処理を求めている場合。

しかし、あなたは(並列処理は、実際の結果の消費量あたりのより多くのリソースのコストでより高速な結果が得られる)、最適なアプローチを求めている場合は、代わりに、単一のクエリでそれを行うことができます。

var query_str = 
    "SELECT doors.mac_addr, " + 
    "sensors.sensor_type as type " + 
    "FROM sensors " + 
    "WHERE (doors.mac_addr = ?) " + 
    "UNION " + 
    "SELECT knobs.mac_addr, " + 
    "furniture.furniture_type as type " + 
    "FROM furnitures" + 
    "WHERE (knobs.mac_addr = ?) " 
; 

あなたが実行する。この方法データベースの呼び出しはもちろん、データベースは並列処理を実行しませんが、よりリソース消費量の少ない最適な時間に回答を得るために最善の努力をします。

リソースがあまり気にしない環境でより速い結果を求めている場合は、さらに多くのリクエストに出席する必要がある場合は平均効率が向上します。良くなります。

+1

結果のマージにはコストがかかります。巨大な量のデータでは、1つのクエリを実行する方が速く、次に2つのクエリを並列処理する方が高速になる可能性があります。 – Eyal

+0

本当です。少なくとも単純な_union_のために。より複雑なマージパターンを並行して最適化する方が簡単です。特に、(別バージョンの)すべてのクエリが巨大でない場合は特に。しかし、一般的に、その真実:メモリ内の巨大なデータ変換を扱うことは、お尻のような痛みです;-) – bitifet

関連する問題