首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >节点js + mongoose,内存不足,花费太多时间。

节点js + mongoose,内存不足,花费太多时间。
EN

Stack Overflow用户
提问于 2015-11-06 02:05:46
回答 1查看 825关注 0票数 1

所以我有这个问题。我使用节点js + mongoose,尝试向用户推荐一部电影。背后的数学是很简单的,你检查其他用户对一部电影的评价,找出与你相似的人,然后你用它来预测某部电影的评分。你对所有的电影都这样做,然后推荐那些预测评分最高的电影。在我的数据库中,我已经获得了100 K的收视率,有1,6k部电影和大约950名用户(从电影中获得了数据集)。我有一个打分的模型,它有电影,标题,价值和用户。使用下面的代码,我可以预测一部电影,但是,当我试图使用循环来预测所有的1,k6电影时,我得到了这个msg“致命错误: CALL_AND_RETRY_LAST分配失败-内存中的进程”。我想我实现的方式占用了太多的内存。这也需要很多时间。大约3-4秒来预测一部电影,这意味着大约100分钟来预测所有的1,6k电影。有人对改进有什么建议吗?我对nodejs非常陌生,这种异步环境让我感到不舒服。这是我的代码:

代码语言:javascript
复制
Rating.find({title:"Batman Forever (1995)"}, function(err,rating){
    if (err) throw err;
    var tempSimilarValues = [];
    var count = 0;
    Rating.find({user: userV}, function(err,result) {
        var tempMovieV;
        var tempRatingArrayV = [];
        var tempMovieArrayV = [];
        while (result.length>0) {
            tempMovieV=result.pop();
            tempMovieArrayV.push(tempMovieV.movieid);
            tempRatingArrayV.push(tempMovieV.value);
        }
        //calculating averageRatingV
        var ratingV;
        var avarageRatingV=0;
        var countV=0;
        for(ratingV in tempRatingArrayV){
            countV++;
            avarageRatingV=avarageRatingV+tempRatingArrayV[ratingV];
        }
        avarageRatingV=avarageRatingV/countV;
        rating.forEach(function(obj){
            Rating.find({user: obj.user}, function(err,result2) {

                var tempRatingArray = [];
                var tempMovieArray = [];
                var tempMovie;
                var tempAverage=0;
                var ammount = result2.length
                while (result2.length>0) {
                    tempMovie=result2.pop();

                    tempMovieArray.push(tempMovie.movieid);
                    tempAverage=tempAverage+tempMovie.value
                    tempRatingArray.push(tempMovie.value);

                }

                var averageU=tempAverage/ammount;
                var similar = calSim(tempRatingArrayV,tempRatingArray, tempMovieArrayV, tempMovieArray);

                if(obj.user!=userV){
                    tempSimilarValues.push([similar,obj.user,obj.value,averageU]);
                }

                count++;

                if(count == rating.length){


                    tempSimilarValues.sort(function (a,b){
                        if (a[0] > b[0]) {
                            return -1;
                        }
                        if (a[0] < b[0]) {
                            return 1;
                        }
                        // a must be equal to b
                        return 0;

                    });

                    var similarValues=tempSimilarValues.slice(0,k);
                    var similarity;
                    var teller=0;
                    var nevner=0;
                    for (similarity in similarValues){
                        teller=teller+similarValues[similarity][0]*(similarValues[similarity][2]-similarValues[similarity][3]);
                        nevner = nevner + similarValues[similarity][0];
                    }

                    var pred = avarageRatingV + teller/nevner;
                    console.log(pred);
                }
            })
        })

    })

})
EN

回答 1

Stack Overflow用户

发布于 2015-11-06 10:07:08

使用回调来嵌套多个方法的代码将使您最终使用回滚地狱。处理场景的一个更好的方法是使用异步库,特别是它的系列()瀑布()方法。

为了举例说明这一点,使用类似的简短示例执行类似的多次回调操作,以查找属于用户的评级(代码一),查找属于某个标题的一些评级(代码2),计算平均评等(代码3),然后计算预测等级最高的评等(代码4):

代码语言:javascript
复制
codeOne(function(a){
    codeTwo(function(b){    
        codeThree(function(c){
            codeFour(function(d){
                // Final callback code        
            })
        })       

    })
})

应用系列方法以串联方式运行函数的任务数组,每个函数运行一次之前的函数已经完成。如果本系列中的任何函数将错误传递给回调函数,则不再运行函数,并立即使用错误值调用回调。否则,回调将在任务完成时接收结果数组。

代码语言:javascript
复制
async.series([
    function(callback){
        // code one
        callback(null, 'one')
    },
    function(callback){
        // code two
        callback(null, 'two')
    },
    function(callback){
        // code three
        callback(null, 'three')
    },
    function(callback){
        // code four
        callback(null, 'four')
    }],
    // optional callback
    function(err, results){
        // results is ['one', 'two', 'three', 'four']
        // final callback code
    }
)

应用瀑布方法以串联方式运行函数的任务数组,每个方法将其结果传递给数组中的下一个。但是,如果任何任务将错误传递给它们自己的回调,则不会执行下一个函数,并且将立即使用错误调用主回调。

代码语言:javascript
复制
async.waterfall([
    function(callback){
        // code one
        callback(null, 'one', 'two')
    },
    function(arg1, arg2, callback){
        // arg1 is equals 'one' and arg2 is 'two'
        // code three
        callback(null, 'three')
    },
    function(arg1, callback){      
        // arg1 is 'three'
        // code four
        callback(null, 'four');
    }], function (err, result) {
        // result is 'four'    
    }
)

在您的示例代码中,建议将其重构为使用瀑布方法。下面是我关于使用异步库实现逻辑的说明,而不是100%肯定您正在尝试实现的目标,因此这可能不起作用,但您可能会得到这样的概念:

代码语言:javascript
复制
async.waterfall([
    function(callback){
        // code one - calculate the average rating for user
        Rating.find({user: userV}, function(err,result) {
            if (err) callback(err);         

            var ratingV,
                avarageRatingV = 0,
                countV = 0,
                tempRatingArray = result.map(function(rating){
                    return rating.value;
                }),
                tempMovieArrayV = result.map(function(rating){
                    return rating.movieid;
                });

            //calculating averageRatingV            
            for(ratingV in tempRatingArrayV){
                countV++;
                avarageRatingV = avarageRatingV + tempRatingArrayV[ratingV];
            }
            avarageRatingV=avarageRatingV/countV;
            callback(null, avarageRatingV, tempRatingArrayV, tempMovieArrayV);
        })
    },
    function(arg1, arg2, arg3, callback){
        // arg1 equals averageRatingV 
        // arg2 equals tempRatingArrayV
        // arg3 equals tempMovieArrayV
        // code to return the users for "Batman Forever (1995)" movie ratings
        Rating.find({ title: "Batman Forever (1995)" }, function(err, ratings){
            if (err) callback(err);
            var users = ratings.map(function(r){ return r.user; });
            callback(null, arg1, arg2, arg3, users);
        });         
    },
    function(arg1, arg2, arg3, arg4, callback){      
        // arg1 is averageRatingV, 
        // arg2 equals tempRatingArrayV, 
        // arg3 equals tempMovieArrayVis ratings 
        // arg4 is the users array for "Batman Forever (1995)" movie ratings
        // code to return
        Rating.find({"user": { "$in": arg4 }}, function(err, result) {
            // do the necessary calculations here
            callback(null, result);
        });
    }], function (err, result) {
        // final result   
    }
)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33558275

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档