2016-11-24 48 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

只是一个额外的笔记没有你的完整的源代码我无法测试,所以这个例子只是显示了原理 –