2016-06-16 1 views
1

나는 아래의 데이터에서 그래픽 라인 차트에 대한 데이터를 생성하는 동안 몇 가지 문제가있는 SAILSJS 프로젝트를 작업 중입니다.라인 그래프를 그리기위한 Mapreduce 도움말

[{ "_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"일이 좋아입니다.

아래의 출력에서 ​​두 날짜 사이에 매일 4 시간의 간격으로이를 얻기 위해 집계를 사용했습니다. 특정 기간 동안 어떤 게임 코어 레코드도 없다면 데이터 포인트는 예상대로 데이터 포인트가 생성되지 않고 gmscore는 0을 반영합니다.

두 날짜

[{ "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 }] 

내가 맵리 듀스를 사용하여 꽤 새로운 오전,하지만 난이 맵리 듀스을 달성 할 수있어 매일 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

안녕하세요 @ 조오, 입력 해 주셔서 감사합니다, 먼저 내 가난한 영어에 대한 apolosize. 위의 생성 된 대답은 정확하지만 부분적으로, 여기에있는 주요 문제는 "createdAt"에 관계없이 4 시간 간격이 필요합니다. 위의 응답은 해당 간격에서 사용할 수있는 데이터가없는 경우 제공되지 않습니다. 어떻게 끝났어? 귀하의 회신을 찾고 있습니다. –

+0

@chridam, 제발 들여다주세요. –

+0

@AyyappaA를 사용하여 누락 된 값을 클라이언트쪽에 직접 삽입해야합니다. map-reduce 단계에서이를 수행 할 방법이 없습니다. – joao

관련 문제