1

我正在尝试从我的 mongodb 上的多个请求中构建一个 JSON。因为我没有使用 DBRef,所以我必须自己构建“表关节”,这就是我最终陷入困境的原因。这是几天以来让我头疼的代码。(mongo部分是用mongoskin完成的)

        var getUserFeed = function(thelimit, out) {
          userfeed = db.collection("userfeed");
          apparel = db.collection("apparel");
          store = db.collection("stores");
          if(thelimit)
            args = {limit:thelimit, sort: [['date',-1]]};

          userfeed.find({},args).toArray(function(e, feed) {
            if (e) console.log("error: ", e);
            // gather aparel infos
            var i=0;
            var ret_feeds = [];
            feed.forEach(function(cur_feed) {
                var outfits=[];
                console.log("beginning with: " + cur_feed.url);
                var resfeed = "";
                resfeed = cur_feed;
                resfeed.url = baseurl + snapurl + resfeed.url + "_small.jpg";
                i=0;
                cur_feed.apparel_ids.forEach(function(item) {
            /*>>*/  apparel.find({"_id": item},{limit:1}).toArray(function(e, results) {
                        console.log(">>>>>>>>>>> APPAREL_FIND { i:" + i + "}");
                        if (e) console.log("error: ", e);
                        results = results[0];
                        if(results.apparel_cat == 1)
                            url_subcat = "pants/";
                        else if(results.apparel_cat == 2)
                            url_subcat = "shirts/";
                        else if(results.apparel_cat == 2)
                            url_subcat = "tshirts/";

                        results.thumb = baseurl + outfiturl + url_subcat + results.apparel_id + "/front.jpg";
                        results.size = "M"; ///// TOBE REAL VERY SOON
                        results.gallery = [
                            baseurl + outfiturl + url_subcat + results.apparel_id + "/model.jpg",
                            baseurl + outfiturl + url_subcat + results.apparel_id + "/front.jpg"
                        ];
                        outfits.push(results); // quick and dirty, 2 b refined..
                        i++;
                        if(i>=cur_feed.apparel_ids.length)
                        {
                            // pack it up
        //                  resfeed.url = resfeed.url;
                            resfeed.outfits = outfits;
                            resfeed.fav = false;
                            resfeed.bough = false;

                            // retrieve store infos
                /*>>>*/     store.find({"_id":resfeed.store_id}, {limit: 1}).toArray(function(e, resstore) {
                                console.log("\t############# STORE_FIND { i:" + i + "}");
                                if (e) console.log("error: ", e);
                                resfeed.store = resstore[0];
                                resfeed.store.class = "hem";
                                ret_feeds.push(resfeed);
                                if(ret_feeds.length >= feed.length)
                                {
                                    console.log("\t\t@@@@@@@@@@@@@@@@@@@@@@calling return [ ret_feeds.length = " + ret_feeds.length + " feed.length = " + feed.length);
                                    out.send(ret_feeds);
                                }
                            });
                        }
                  });
                });
            });
          });
        }

此代码失败,因为在完成其任务之前返回了 json,所以下次它尝试返回另一个 json 时,由于标头已经发送,它会惨遭崩溃。

现在如您所见,我有 3 个集合:用户源、服装和商店。此函数的目标是检索 userfeed 集合中的所有项目,提取服装(基于作为 userfeed 集合的一部分的 suit_id 数组),并以相同的方式提取与每个 userfeed 条目相关的商店信息,像这样:

在此处输入图像描述

我知道 async.js 或等效的方法是要走的路:我已经像 SO 上的无数其他帖子一样红了,但我仍然无法理解它,可能是因为 async.js 背后的整个机制或一般的流量控制,我仍然没有关注它。我仍然是节点的菜鸟:)

更新

我想我在这里找到了正确的理解途径:http ://www.sebastianseilund.com/nodejs-async-in-practice

这家伙在逐个用例描述将 async.js 应用到您的代码的所有方法方面做得非常出色。我会尽快发布解决方案。

更新 2

感谢上面的家伙,我可以制定一个可行的解决方案,下面是答案。

4

1 回答 1

0

经过这么多的挣扎,我终于设法得到了解决方案。async.js 是我(显然)怀疑的答案。

仅供参考,这是工作代码。如果您想指出改进或其他任何内容,我们非常欢迎您

var getUserFeed = function(thelimit, out) {
userfeed = db.collection("userfeed");
apparel = db.collection("apparel");
store = db.collection("stores");
var args;
if(thelimit)
    args = {limit:thelimit, sort: [['date',-1]]};

var outfits=[];
var feeds = array();

async.series([
    // userfeed find
    function(callback) {
        userfeed.find({},args).toArray(function(e, feed) {
            if(e) callback(e);
            feeds = array(feed);
            console.log(feeds.length + " retrieved. stepping in");
            callback(null, null);
        });
    },

    // join
    function(callback) {
        async.forEach(feeds, function(thefeed, callback) {
            var i = feeds.indexOf(thefeed);
            async.parallel([
                // load apparel infos
                function(callback) {
                    console.log("\t >>> analyzing thefeed id " + thefeed._id);
                    async.forEach(thefeed.apparel_ids, function(apparel_id, callback) {
                        apparel.find({"_id": apparel_id},{limit:1}).toArray(function(e, results) {
                            if (e) console.log("error: ", e);
                            results = results[0];
                            if(results.apparel_cat == 1)
                                url_subcat = "pants/";
                            else if(results.apparel_cat == 2)
                                url_subcat = "shirts/";
                            else if(results.apparel_cat == 2)
                                url_subcat = "tshirts/";

                            results.thumb = baseurl + outfiturl + url_subcat + results.apparel_id + "/front.jpg";
                            results.size = "M"; ///// TOBE REAL VERY SOON
                            results.gallery = [
                                baseurl + outfiturl + url_subcat + results.apparel_id + "/model.jpg",
                                baseurl + outfiturl + url_subcat + results.apparel_id + "/front.jpg"
                            ];
                            console.log("\t\t### pushing data into thefeed_index: " + i);
                            if(!util.isArray(feeds[i].oufits)) feeds[i].outfits = array();
                            feeds[i].outfits.push(results);
                            callback(null, null);
                        });
                    }, callback);
                },
                // load store infos
                function(callback) {
                    store.find({"_id":thefeed.store_id}, {limit: 1}).toArray(function(e, resstore) {
                        console.log("\t### STORE_FIND");
                        if (e) console.log("error: ", e);
                        feeds[i].store = resstore[0];
                        feeds[i].store.class = "hem";
                        callback(null, null);
                    });
                }
            ], callback);
        }, callback);
    }

    // MAIN
    ], function(err, result) {
        console.log("feed retrieval completed. stepping out");
        if (err) return next(err);
        out.send(feeds);
    });
};
于 2013-10-16T20:34:12.227 回答