2015-06-25 27 views
1

我需要幫助通過get請求從數據庫中提取對象的對象,因此我可以在我的網頁上顯示所有對象,但是我運行的這個測試已經失敗,調試它,它只是永遠運行,JSON永遠不會被收到。我認爲我的邏輯可能會在某個地方混亂。我不確定是否應該爲此使用異步,它看起來像回調地獄,現在考慮我可能應該,但我不知道如果考慮優化如果這是一個體面的方式,我通常從最糟糕的情況是,我試圖低於O(N)的目標,因爲總共有N個文檔,我只是遍歷一個遞歸樹,還有一些額外的查詢來查找最初的文檔以及什麼不是這樣,N + X(其中x是額外的查詢量< N)。但我覺得我好像錯過了一些概念上的東西,好像可能有更好的方法。樹上的遞歸類似於貓鼬文檔的結構

我有一個模式,這樣

Doc { 
title : string, 
author : string, 
subDoc : [{type: mongoose.Schema.Types.ObjectId, ref : 'Doc'}] 
} 

東西,所以也有我生成的文件,每次我產生這些文件我都可以存在的這些文件,即使是那些子文檔可以有子文檔的子文檔。然後我們結束了一些樹狀結構。但我不想顯示文檔>然後它的sub_doc1>所有的子分區...等>其子文檔2>所有的子文檔..>等。

但是我不知道是什麼我認爲是有效率的,如果它甚至值得做這麼多的查詢。

app.get('/docs/:doc/subDocTree', function(req, res) { 
    var array = []; 
    var id = req.params.doc; 
    var num_proc = 0; 
    console.log(id); 
    Doc.findById(id, function(err, doc) { 
     console.log(doc); 
     for (var x = 0; x < doc.subDoc.length; x++) { 
      Doc.findById(form.subDoc[x], function(err, subDoc) { 
       populate(subDoc); 
      }); 
     } 
     num_proc = num_proc + 1; 
     if (num_proc == Doc.subDoc.length) { 
      res.json(array); 
      array.length = 0; 
     } 
    }); 
}); 

function populate(docs) { 
    var num_proc = 0; 
    Form.findById(docss, function(err, doc) { 
     if (doc.subform.length != 0) { 
      //console.log(form); 
      var total = doc.subDoc.length; 
      for (var i = 0; i < total; i++) { 
       array.push(doc.subDoc[x]); 
       num_proc = num_proc + 1; 
       populate(subDoc[x]); 
      } 
     } 
    }); 
} 

我認爲搜索文檔,然後再尋找其所有的子文檔,然後遞歸與SUBDOCS的任何SUBDOCS會工作的填入方法檢查。然而,我永遠不會收到JSON,並且通過使用print語句/ console.logs進行調試,我仍然無法弄清楚我出錯的地方。

+1

在該行不'array'超出範圍'的Array.push(doc.subDoc [X]);'? – dcco

+0

另一件事:通過提供最大遞歸深度來避免循環對象,這通常會導致無限循環。 –

+0

是啊,陣列是,它應該是全球性的,並感謝勝利者。 – Karan

回答

1

您的代碼是async,不適用於for循環。

for (var x = 0; x < doc.subDoc.length; x++) { 
    Doc.findById(form.subDoc[x], function(err, subDoc) { 
     populate(subDoc); 
    }); 
} 
num_proc = num_proc + 1; 
if (num_proc == Doc.subDoc.length) { 
    res.json(array); 
    array.length = 0; 
} 

res.json(array)將前populate(subDoc)

您應該使用異步庫或承諾處理這個執行

另外貓鼬已經有一個內置的方法來填充子文件。


**** ****更新

看來,你會從這個模塊中受益:deep-populate

與承諾相結合這裏的如何我會重新編寫代碼:

首先,我promisify的mongoose對象(使用bluebird

// Promisification 
var Promise = require('bluebird'); 
var mongoose = require('mongoose'); 
Promise.promisifyAll(mongoose); 

然後在架構定義我會使用深填入插件

var deepPopulate = require('mongoose-deep-populate'); 
Doc.plugin(deepPopulate, options); 

所以,現在你的路線是這樣的:

app.get('/docs/:doc/subDocTree', function(req, res) { 
    var id = req.params.doc; 

    Doc.findById(id).deepPopulate('subDoc').execAsync() 
    .then(function(doc){ 
     res.json(doc.subDoc); 
    }).catch(function(err){ 
     // handle error 
     res.send('Something went wrong...' + err.message); 
    }); 
}); 
+0

是的,我給填充方法一槍,但總的來說,我仍然不得不通過我所有的subdoc填充仍然?例如,如果它是Main - > Sub1和Sub2; Sub1> sub3和sub 4; Sub> Sub5和Sub 6如果這是我們的樹,那麼調用populate將只填充一個json一次?從本質上講,你在哪裏推薦異步和承諾? – Karan

+0

我試過了,我仍然返回一個級別的人羣,你打算只用doc返回json嗎?因爲我們通過id找到了doc,並且深入地填充了它,而不是subdoc。我將嘗試閱讀更多的文檔和代碼,並瞭解爲什麼它的人口不是一個水平。 – Karan

+0

對不起,意味着填充* – Karan