1

mongodb で複数のリクエストから JSON を構築しようとしています。私はDBRefを使用していないので、自分で「テーブルジョイント」を作成する必要があり、それがこの混乱に陥った方法です。これは、数日前から頭痛の種になっているコードです。(モンゴ部分はモンゴスキンで仕上げています)

        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 を返そうとすると、ヘッダーが既に送信されているという事実のために惨めにクラッシュします。

ご覧のとおり、userfeed、apparel、stores の 3 つのコレクションがあります。この関数の目的は、userfeed コレクション内のすべてのアイテムを取得し、(userfeed コレクションの一部である outfit_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 に答える