使用express / mongoose嵌套查询

时间:2012-08-07 10:29:45

标签: node.js mongodb express mongoose

我有一个Tag集合,它们只有一个值是标签。它们可以是随机标签或树标签(这里是没有_id的样本):

{
    "label": "/test1"
}
{
    "label": "/test2"
}
{
    "label": "/test1/test1-1"
}
{
    "label": "/test2/test2-1"
}
{
    "label": "/test1/test1-1/test1-1-1"
}
{
    "label": "something"
}

我想要的是在我的标签树上有一个单独的对象:

{
    "/test1": {
        "name": "test1"
      , "children": {
            "/test1/test1-1" : {
                "name": "test1-1"
              , "children": {
                    "/test1/test1-1/test1-1-1" : {
                        "name": "test1-1-1"
                      , "children": {}
                    }
                }
            }
        }
    }
  , "/test2": {
        "name": "test2"
      , "children": {
            "/test2/test1-2" : {
                "name": "test1-2"
              , "children": {}
           }
       }
   }
}

以下是我在我的应用中尝试的内容:

app.get('/tree', function(req, res, next) {
    var tree = {};
    Tag
    // If you have a better solution, I'm not really fan of this
    .$where('this.label.split(new RegExp("/")).length === 2')
    .exec(function(err, tags) {
        tags.forEach(function(tag) {
            tag.getChildren(function(children) {
                tree[tag.label] = {
                    'title':    tag.label
                  , 'children': children
                }
            });
        });
    });
    // do some stuff with the `tree` var
    // which does not work because of the asynchronousity of mongo
});

在我的模型中,它不起作用,起初我想用tag.getChildren()返回树的路径但是,我认为回调将是更好的选择,我停在那里

Tag.methods.getChildren = function(callback) {
    var tree = {};
    Tag
    .$where('this.label.split(new RegExp("' + this.label + '/")).length === 2')
    .exec(function(err, tags) {
        tags.forEach(function(tag) {
            tag.getChildren(function(children) {
                tree[tag.label] = {
                    'title':    tag.label
                  , 'children': children
                }
            });
        });
        return tree
    });
};

我不知道怎么做到这一点,我对Node和异步编程都很陌生,所以任何帮助都会受到欢迎。

2 个答案:

答案 0 :(得分:1)

您可能应该查看async.js模块,该模块支持执行迭代,在每个步骤调用异步代码并在完成所有异步代码时执行回调。

答案 1 :(得分:1)

在这个例子中做多个Mongo请求是愚蠢的,所以我只做了一个,解析结果并创建我的树,如果有人遇到同样的问题,这是我的代码:

app.get('/tree', function(req, res, next) {
    var tree = {}
    Tag
    .find({ label: { $regex: /^\// } }, ['label'])
    // Skip the "/"
    .skip(1)
    .exec(function(err, tags) {
        tags.forEach(function(tag) {
            var split = tag.label.split('/');
            // Root
            if (split.length === 2) {
                tree[_.slugify(split[1])] = {
                    title: split[1]
                  , children: {}
                }
            } else {
                var name = split.pop()
                  , path = tag.label
                  , pathSlug = _.slugify(path.replace(/\//g, '-'))
                  , parentPath = path.split('/')
                  , parentSlug = ''
                  , parent;
                parentPath.shift();
                parentPath.pop();
                parentPath.forEach(function(step) {
                    step = parentSlug ? parentSlug + '-' + _.slugify(step) : _.slugify(step);
                    parentSlug = step;
                    parent = parent ? parent.children[step] : tree[step];
                });
                if (!parent) {
console.error('ERROR :')
console.log(tag.label)
console.log(path.split('/'))
console.log(name)
console.error('##################')
                } else {
                    parent.children[pathSlug] = {
                        title: name
                      , children: {}
                    }
                }
            }
        });
        res.send(tree, 200);
    });
});