2016-11-24 123 views
1

要爲代碼設置場景,數據庫將存儲文檔,並且每個文檔都有可能將圖像與它們關聯。Node.js異步嵌套mysql查詢

我一直在試圖編寫一個查詢數據庫的路徑,以查找與它們相關的每個文檔,將這些數據存儲在JSON中,這些數據在完成時返回到ajax請求,因此可以在頁面上查看數據。我目前得到的最接近的是下面的嘗試(見代碼)。

router.post('/advanced_image_search', userAuthenticated, function(req, res, next) { 

    async.waterfall([ 
    // First function is to get each document which has an image related 
    function getDocuments(callback){ 
     connection.query(`SELECT DISTINCT(Document.document_id), Document.doc_name, Document.doc_version_no, Document.doc_date_added 
     FROM Document WHERE doc_type = 'image'`, function(err, results) { 
     if (err) { 
      callback(err, null); 
      return; 
     } 

     // The Object containing the array where the data from the db needs to be stored 
     var documents = { 
      'docs': [] 
     }; 

     // foreach to iterate through each result found from the first db query (getDocuments) 
     results.forEach(function(result) { 

      // New object to store each document 
      var document = {}; 

      document.entry = result; 

      // This is the array where each image assciated with a document will be stored 
      document.entry.images = []; 
      // Push each document to the array (above) 
      documents.docs.push(document); 

      var doc_id = result.document_id; 
     }) 
     // Returning the results as 'documents' to the next function 
     callback(null, documents); 
     }) 
    }, 
    function getImages(documents, callback){ 

     // Variable assignement to the array of documents 
     var doc_array = documents.docs; 

     // Foreach of the objects within document array 
     async.forEachOf(doc_array, function(doc, key, callback){ 
     // Foreach object do the following series of functions 
     async.waterfall([ 
      function handleImages(callback){ 

      // The id of the document to get the images for 
      var doc_id = doc.entry.document_id; 
      connection.query(`SELECT * FROM Image, Document WHERE Image.document_id = '${doc_id}' AND Image.document_id = Document.document_id`, function(err, rows) { 
       if (err) { 
       callback(err, null); 
       return; 
       } 

       callback(null, rows); 
      }) 
      }, 
      // Function below to push each image to the document.entry.images array 
      // 
      function pushImages(rows, callback){ 
      // If multiple images are found for that document, the loop iterates through each pushing to the images array 
      for (var j = 0; j < rows.length; j++) { 

       // Creating new object for each image found so the data can be stored within this object, then pushed into the images array 
       var image = { 
       'image_name': rows[j].image_name 
       }; 

       doc.entry.images.push(image); 
      } 
      callback(null, doc_array); 

      } 

     ], function(err, doc_array){ 

      if (err) { 
      console.log('Error in second waterfall callback:') 
      callback(err); 
      return; 
      } 
      console.log(doc.entry); 
      // callback(null, doc_array); 
     }) 
     }, function(err, doc_array){ 

     if (err) { 
      callback(err); 
      return; 
     } 

     callback(null, doc_array); 

     }); 
     callback(null, doc_array); 
    } 
    ], function(err, doc_array) { 

    if (err){ 
     console.log('Error is: '+err); 
     return; 
    } 

    // The response that should return each document with each related image in the JSON 
    res.send(doc_array); 
    }) 

}); 

目前返回的結果是:

1: 
{entry: {document_id: 1, doc_name: "DocumentNameHere", doc_version_no: 1,…}} 
entry: 
{document_id: 1, doc_name: "DocumentNameHere", doc_version_no: 1,…} 
doc_date_added:"2016-10-24" 
doc_name:"DocumentNameHere" 
doc_version_no:1 
document_id:1 
images:[] 

以上可以看出,即使與測試中,圖像被發現(的console.log)圖像陣列保持爲空。

我希望有人能夠幫助這一點,因爲我在努力尋找這一複雜的問題。

謝謝

+0

如果你對此有何評論'//返回結果爲「文檔」下一個function'你實際上並沒有從任何回報功能,但你應該。 – marekful

+0

@marekful我只是做了一個console.log(文件);在下一個函數(getImages())中,所有文檔都將返回給它。我認爲問題存在於async.forEachOf()的末尾。它似乎沒有傳遞改變的JSON – JRich5

回答

0

有幾個異步操作在這裏進行,每個操作都需要一個回調。參見修改後的代碼:

router.post('/advanced_image_search', userAuthenticated, function(req, res, next) { 

    var getDocuments = function(next) { 
    // Function for getting documents from DB 
    var query = `SELECT DISTINCT(Document.document_id), Document.doc_name, Document.doc_version_no, Document.doc_date_added FROM Document WHERE doc_type = 'image'`; // Set the query 
    connection.query(query, function(err, results) { 
     // Run the query async 
     if(err) { 
      // If err end execution 
      next(err, null); 
      return; 
     } 

     var documentList = []; // Array for holding docs 
     for(var i=0; i<results.length; i++) { 
      // Loop over results, construct the document and push to an array 
      var documentEntry = results[i]; 
      var documentObject = {}; 
      documentObject.entry = documentEntry; 
      documentObject.entry.images = []; 
      documentObject.id = documentEntry.document_id; 
      documentList.push(documentObject); 
     } 
     next(null, documents); // Pass to next async operation 
     }); 
    }; 

    var getImages = function(documents, next) { 
    // Function for getting images from documents 
    var finalDocs = []; // Blank arry for final documents with images 
    for (var i=0; i<documents.length; i++) { 
     // Loop over each document and construct the query 
     var id = documents[i].id; 
     var query = `SELECT * FROM Image, Document WHERE Image.document_id = '${doc_id}' AND Image.document_id = Document.document_id`; 

     connection.query(query, function(err, images) { 
     // Execute the query async 
     if(err) { 
      // Throw error to callback 
      next(err, null); 
      return; 
     } 
     var processedDoc = processImages(documents[i], images); // Call a helper function to process all images into the document object 
     finalDocs.push(processedDoc); // Push the processed doc 

     if(i === documents.length) { 
      // If there are no more documents move onto next async 
      next(null, finalDocs); 
     } 
     }); 
    } 
    }; 

    var processImages = function(doc, images) { 
    for (var i=0; i< images.length; i++) { 
     // Loop over each document image - construct object 
     var image = { 
     'image_name': rows[j].image_name 
     }; 
     doc.entry.images.push(image); // Push image into document object 
    } 

    return doc; // Return processed doc 
    }; 

    getDocuments(function(err, docs) { 
    if(err) { 
     // Your error handler 
    } 

    if(docs) { 
     getImages(docs, function(err, finalDocs) { 
     if(err) { 
      // Your error handler 
     } 

     if(finalDocs) { 
      console.log(finalDocs); 
      res.status(200).json(finalDocs); // Send response 
     } 

     }); 
    } 

    }); 
}); 
  1. 首先,我們創建一個函數來獲取文件 - 這個函數接受一個回調作爲參數。我們運行我們的查詢並構建我們的文檔列表。然後我們通過執行我們的回調返回文檔列表
  2. 接下來我們運行一個函數來獲取每個文檔的圖像。這個函數接受我們的文檔列表和一個回調作爲我們的參數。它爲每個文檔檢索圖像並調用幫助函數(同步)
  3. 我們的幫助函數將圖像處理到每個文檔並返回處理後的文檔。
  4. 然後,我們通過第二次回調返回一系列處理過的文檔來完成我們的操作。

其他說明

  • 我們可以大潮這件事通過構建這個程序樣式代碼到一個包含JSON對象
  • 在文檔末尾的功能執行的嵌套可清洗進一步
  • 我已經避免使用異步庫,因爲它有助於更​​好地瞭解回調模型
  • 事件發射器可用於平坦十個回調 - 參見https://nodejs.org/dist/latest-v7.x/docs/api/events.html

希望這有助於

迪倫

+0

只是一個額外的筆記沒有你的完整的源代碼我無法測試,所以這個例子只是顯示了原理 –