2016-06-16 4 views
1

私はSAILSJS Projectに取り組んでいます。下のデータからGraphical Line Chartのデータを生成する際に問題があります。Mapreduce linegraphをプロットする

[{ "_id" : "575fcb020d28bbc117647c7a", "childid" : "575a4952bfb2ad01481e9060", "starttime" : "1465895783", "endtime" : "1465895783", "word" : "TOE", "gamescore" : "1", "createdAt" : "2016-06-14T09:14:42.959Z" 
    }, 
    { "_id" : "575fcbd150c93cf819faecfe", "childid" : "575a4952bfb2ad01481e9060", "starttime" : "1465895983", "endtime" : "1465895990", "word" : "SLOW", "gamescore" : "1", "createdAt" : "2016-06-14T09:18:09.453Z" 
    }, 
    {"_id" : "575fcbd150c93cf819faecff", "childid" : "575a4952bfb2ad01481e9060","starttime" : "1465895959", "endtime" : "1465895959", "word" : "GLOW", "gamescore" : "1", "createdAt" : "2016-06-14T09:18:09.454Z" 
    }, 
    { "_id" : "57619851d71451e56949dd4d", "starttime" : "1466013832", "gamescore" : "1", "childid" : "5761973fd71451e56949dd3c", "endtime" : "1466013850", "word" : "YUM", "createdAt" : "2016-06-15T18:02:57.543Z" 
    }, 
    { "_id" : "576198ead71451e56949dd58", "starttime" : "1466014023", "gamescore" : "1", "childid" : "5761973fd71451e56949dd3c", "endtime" : "1466014030", "word" : "BELT", "createdAt" : "2016-06-15T18:05:30.945Z" 
    }, 
    { "_id" : "57619915d71451e56949dd5f", "childid" : "576197c2d71451e56949dd40", "starttime" : "1466013984", "endtime" : "1466013989", "word" : "PLAY", "gamescore" : "1", "createdAt" : "2016-06-15T18:06:13.388Z" 
    }, 
    { "_id" : "57619958d71451e56949dd65", "starttime" : "1466014140", "gamescore" : "1", "childid" : "5761973fd71451e56949dd3c", "endtime" : "1466014143", "word" : "BELL", "createdAt" : "2016-06-15T18:07:20.298Z" 
     }............] 

私は一日、正しいgamescoreのグループ化のために4時間の時間間隔を作ることに助けを探していますと、間違った「1」とgamescoreは、以下の「0」何かが好きです。

以下の出力では、2つの日付の間の各日の4時間間隔でこれを取得するために集計を使用しました。特定の期間のためのgamescoreレコードがない場合、その期間、私はdatapointを期待しているので、データポイントは作成されず、gmscoreはその中に反映されます。

二つの日付

[{ "txnTime" : ISODate("2016-06-10T04:00:00.000Z"),"gmScoreCorrectCount" : 15, "gmScoreWrongCount" : 2 }, 
    { "txnTime" : ISODate("2016-06-10T08:00:00.000Z"),"gmScoreCorrectCount" : 10, "gmScoreWrongCount" : 8 }, 
    { "txnTime" : ISODate("2016-06-13T04:00:00.000Z"),"gmScoreCorrectCount" : 9, "gmScoreWrongCount" : 9 }, 
    { "txnTime" : ISODate("2016-06-14T04:00:00.000Z"),"gmScoreCorrectCount" : 7, "gmScoreWrongCount" : 8 }, 
    { "txnTime" : ISODate("2016-06-14T08:00:00.000Z"),"gmScoreCorrectCount" : 6, "gmScoreWrongCount" : 7 }] 

私はMapReduceのを使用してとかなり新しいですが、私はそれはMapReduceので達成することができる知っているの毎日の4回の間隔で予想される出力:

mapf = function() { 
// round down to nearest hour 
d = this.createdAt; 
d.setMinutes(0); 
d.setSeconds(0); 
d.setMilliseconds(0); 
emit(d, this.gamescore); 
} 

    reducef = function (key, values) { 
var sum = 0; 
for (var v in values) { 
    sum += values; 
} 
return sum; 
    } 

    db.activity.mapReduce(mapf, reducef, {out: { merge : "hourly_logs" }}) 

答えて

0

ファーストあなたのサンプル入力は、あなたが与えたサンプル出力と一貫していないことに注意してください。

それを持って、使用可能な解決策になることができ、問題を解決するためにマップが-削減:

res = db.activity.mapReduce(mapf, reducef, {out: { inline: 1 }})['results']; 

var correctResult; 
if(res.length > 1){ 

    // sort results by created 
    res.sort(function(a, b) { 
     return parseFloat(a._id) - parseFloat(b._id); 
    }); 

    correctResult = [res[0]]; 

    referenceDate = res[0]['_id']; 
    for(var ri = 1; ri<res.length; ri++){ 

     diff = res[ri]['_id'] - referenceDate; 

     // 14400000 milis = 4 hours 
     if (diff > 14400000){ 

      numberOfMissing = Math.ceil((diff - 14400000)/14400000); 

      // inject missing values 
      for(var ni=1; ni <= numberOfMissing; ni++){ 
       correctResult.push({"_id": new Date(referenceDate.getTime()+(14400000*ni)), "value": {"gmScoreCorrectCount": 0, "gmScoreWrongCount": 0}}); 
      } 

     } 

     correctResult.push(res[ri]); 

     referenceDate = res[ri]['_id']; 

    } 

}else{ 

    correctResult = res; 

} 

mapf = function() { 

    d = new Date(this.createdAt); 

    // bucket every 4 hours 
    d.setHours(d.getHours()-(d.getHours()%4)); 

    // remove minutes, seconds and milis from date 
    d.setMinutes(0); 
    d.setSeconds(0); 
    d.setMilliseconds(0); 

    gscore = parseInt(this.gamescore); 

    gmScoreCorrectCount = 0; 
    gmScoreWrongCount = 0; 
    if(gscore > 0){ 
     gmScoreCorrectCount += 1; 
    }else{ 
     gmScoreWrongCount += 1; 
    } 

    emit(d, {"gmScoreCorrectCount": gmScoreCorrectCount, "gmScoreWrongCount": gmScoreWrongCount}); 
} 

reducef = function (key, values) { 

    var gmScoreCorrectCount = 0; 
    var gmScoreWrongCount = 0; 

    for (var i=0; i<values.length; i++) { 
     v = values[i] 
     gmScoreCorrectCount += v['gmScoreCorrectCount']; 
     gmScoreWrongCount += v['gmScoreWrongCount']; 

    } 
    return {"gmScoreCorrectCount": gmScoreCorrectCount, "gmScoreWrongCount": gmScoreWrongCount}; 
} 

不足している結果注入工程は、クライアント側では、外部に行われる必要があります

reduce関数は、偶数でなければならないので、emit値は縮小値形式に従わなければならないことに注意してください。Read more about it here

質問とは別に、処理とクエリを複雑にするデータについてのコメントがあります。まず、数値(gamescoreなど)を文字列として保存しないでください。同じことが日付とタイムスタンプにも適用されます(mongoにはDATEオブジェクトがあるので、それらを使用するように努力する必要があります)。

+0

こんにちは@joao、あなたの入力をありがとう、最初私は私の貧しい英語のためにapolosize。上記の答えは正解ですが、部分的には、ここでの主な問題は「createdAt」とは無関係に4時間間隔が必要です。どのように私はそれ以上来ることができます。あなたの返事を探しています。 –

+0

@chridam、それを見てください。 –

+0

@AyyappaAあなたがクライアント側で自分で注入する必要がある欠損値を追加します。 map-reduceステップでそれを行う方法はありません。 – joao

関連する問題