2016-08-08 19 views
8

Używam modułu reszta node.js. Mam interfejs REST API, który wyprowadza wynik pojedynczego zapytania MySQL w json. Oto kod interfejsu API;Połącz dane wyjściowe z 2 zapytań w interfejsie API REST

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); 
}; 

Załóżmy, że mam inne zapytanie, które wygląda mniej więcej tak;

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

Chcę połączyć wyjście 2 MySQL odpytuje query_str i query_str_2 i mieć API REST zwraca wynik w json. Jak to zrobić?

Aby być bardziej zrozumiałym, myślę o kodzie robiącym coś takiego;

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: zacząłem bounty przyciągnąć odpowiedzi, które korzystają z obietnic.

+1

Pytasz, jak wykonać dwa zapytania lub czy naprawdę zadajesz pytanie SQL dotyczące wykonywania złączeń? – HeadCode

+0

Kod nagłówka, Przepraszamy, że nie jest jasne. To nie jest pytanie SQL. Pytam, jak zrobić 2 kwerendy i zwracając połączony wynik z 2 kwerend w json. Zmieniłem to pytanie, aby było jaśniejsze. Dziękuję Ci. –

+1

Trudną częścią tego problemu jest asynchroniczny charakter node.js. Zapytania nie mogą być uruchamiane jedna po drugiej. Ciekawie będzie zobaczyć, w jaki sposób obietnice lub moduły, takie jak bluebird, są wykorzystywane do udzielenia odpowiedzi na to pytanie. – user781486

Odpowiedz

6

Moduł do zarządzania asynchronicznym sterowaniem przepływem - taki jak async - może ci w tym pomóc.

Na przykład:

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

Dzięki. Rewizja. Wypróbuję to. Czy przypadkiem wiesz, w jaki sposób rozwiązanie może korzystać z obietnic lub czegoś w rodzaju modułu bluebird? –

+1

Kod w pytaniu dotyczył API opartego na oddzwonieniu, więc moja odpowiedź wzięła to pod uwagę. Tak, możesz użyć obietnic, ale musisz użyć czegoś takiego jak bluebird [promisify] (http://bluebirdjs.com/docs/api/promise.promisify.html), aby przekonwertować interfejs API oparty na wywołaniach zwrotnych na obietnicę- oparty API. Po uzyskaniu interfejsu API, który zwróci obietnice, możesz zrobić [Promise.all] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all), aby "połączyć" wyniki. – cartant

+0

Dzięki. Domyślam się, że twoje rozwiązanie korzystające z callbacków i asynchronizacji byłoby najatrakcyjniejsze, ponieważ oryginalny kod obejmował interfejs API oparty na wywołaniach zwrotnych. –

3

Jeśli proszą o równoległości, jak @cartant mówi, można użyć asynchronicznie lub (znacznie lepiej) obietnice (Promise.all(p1, p2).then(...)).

Ale jeśli proszą o optymalnym podejściem (równoległość daje szybsze rezultaty kosztem większych środków na rzeczywiste zużycie wynikowego), można to zrobić w jednym zapytaniu Zamiast:

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 = ?) " 
; 

W ten sposób można wykonać pojedyncza baza danych i, oczywiście, baza danych nie będzie działać równolegle, ale zamiast tego dołoży wszelkich starań, aby uzyskać najlepszą odpowiedź przy niższym zużyciu zasobów.

Tak więc, jeśli musisz wziąć udział w jeszcze większej liczbie zgłoszeń, średnia wydajność będzie lepsza, z drugiej strony, jeśli chcesz uzyskać szybsze wyniki w środowisku, w którym zasoby nie są zbyt ważne, to podejście równoległe będzie lepiej.

+1

Łączenie wyników jest również kosztowne. Możliwe, że przy dużej ilości danych szybciej będzie wykonać jedno zapytanie, a następnie dwa równolegle. – Eyal

+0

Tak, to prawda. Przynajmniej na proste _union_.Bardziej skomplikowane wzory łączenia mogą być łatwiejsze do optymalizacji równolegle. Zwłaszcza wtedy, gdy nie wszystkie zapytania (w oddzielnej wersji) są ogromne. Ale ogólnie rzecz biorąc, to prawda: obsługa ogromnych transformacji danych w pamięci jest jak ból w dupie ;-) – bitifet

Powiązane problemy