2015-06-25 3 views
1

Мне нужна помощь, вытаскивающая объекты объектов из моей базы данных через запрос на получение, поэтому я могу отобразить все это на своей веб-странице, но этот тест, который я выполнял, уже не удался, отлаживая его, он просто работает вечно, и JSON так и не получил. Я думаю, что моя логика может быть испорчена. Я не уверен, должен ли я использовать async для этого, это похоже на обратный ад, и теперь, думая об этом, я, вероятно, должен, но я не знаю, думает ли в оптимизации, если это приличный способ, я обычно начинаю с в худшем случае, и с попыткой, с которой я столкнулся ниже того, к чему я стремился, было около O (N), так как есть N полных документов, и я просто пересекаю дерево рекурсии, с некоторыми дополнительными запросами на поиск исходных документов и что не так, N + X (где x - дополнительное количество запросов < N). Но мне кажется, что я пропускаю что-то концептуально, как будто может быть лучший способ.Рекурсия на дереве как структура документов мангуста

У меня есть схема, что-то вроде этого

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

Таким образом, есть документы, которые я генерировать и каждый раз, когда я произвожу эти документы у меня есть поддокументы, которые могут существовать в этих документах, и даже те, вложенные документы могут иметь поддокументы. Затем мы получаем некоторую древовидную структуру. Однако я не буду отображать Документ>, а затем его sub_doc1> все его поддомены ... и т. Д.> Его sub doc2> все его вспомогательные документы ..> и т. Д.

Однако я не знаю, Я думаю, что это эффективно, и если это стоит делать с этими многочисленными запросами.

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, и, отлаживаясь с помощью операторов печати/console.logs, я все еще не мог понять, где я ошибся.

+1

Не 'array' из области видимости в линии 'Array.push (doc.subDoc [х]);'? – dcco

+0

Другое: избегать круговых объектов, обеспечивая максимальную глубину рекурсии, которая обычно может привести к бесконечному циклу. –

+0

Да, массив, он должен быть глобальным и благодарить победителя. – Karan

ответ

1

Ваш код isync, который не работает для цикла.

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)

Вы должны либо использовать библиотеку асинхронной или обещает справиться с этим.

Также mongoose уже имеет встроенный метод для заполнения вспомогательных документов.


**** Обновление ****

Кажется, вы извлечь выгоду из этого модуля: 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

Да, я дал метод популяции выстрелом, но во всем останетесь ли мне еще заполнять все мои поддоны? Например, если это были Main -> Sub1 и Sub2; Sub1> sub3 и sub 4; Sub> Sub5 и Sub 6, если это было наше дерево, тогда вызов population будет заполнять только json сразу? в сущности, это то, что вы предложили асинхронным и обещаниям? – Karan

+0

Я пробовал это, и я все еще возвращался с населением на один уровень, и вы хотели вернуть json только с документом? Потому что мы нашли doc по id и глубоко заполнены, а не subdoc. Я попытаюсь прочитать больше документации и моего кода и посмотреть, почему это не популяция за один уровень. – Karan

+0

Извините, это означало население * – Karan

Смежные вопросы