树上的递归就像猫鼬文件的结构一样

时间:2015-06-25 20:59:00

标签: node.js algorithm mongodb recursion mongoose

我需要帮助通过get请求从数据库中提取对象的对象,所以我可以在我的网页上显示所有这些对象,但是我运行的这个测试已经失败,调试它,它只是永远运行而且JSON是从未收到过。我认为我的逻辑可能会搞砸到某个地方。我不确定我是否应该使用异步,它确实看起来像回调地狱,现在我可能应该考虑它,但我不知道如果想在优化中这是一个不错的方式,我通常从最糟糕的情况,并且尝试我在我的目标下运行的是O(N),因为有N个文档,我只是遍历一个递归树,还有一些额外的查询来查找初始文档和什么不是这样,N + X(其中x是额外的查询量< N)。但我觉得好像我错过了概念上的某些东西,好像可能有更好的方法。

我有一个架构,类似这样的

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

所以我生成的文档和每次生成这些文档时都有这些文档可以存在的子文档,甚至那些子文档也可以有子文档。然后我们最终得到一些树状结构。但是,我不想显示文件>那么它的sub_doc1>所有的子网...等等>其子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]);
            }
        }
    });
}

我认为首先搜索文档,然后搜索其所有子文档,然后使用populate方法递归检查子文件的任何子文件都可以。但是我永远不会收到JSON,并且通过使用print statements / console.logs调试,我仍然无法弄清楚我哪里出错了。

1 个答案:

答案 0 :(得分:1)

您的代码是异步的,不能用于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)

您应该使用异步库或承诺来处理此问题。

此外,mongoose已经有一个内置的方法来填充子文档。

**** ****更新

您似乎可以从此模块中受益:deep-populate

结合承诺以及我如何重新编写代码:

首先,我宣传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);
    });
});