2013-01-08 2 views
0

저는 MongoDb을 처음 사용하고 MapReduce 또는 Aggregation에 대한 직업을 가지고 있습니다.인보이스 발행 통계를위한 MongoDb aggregation 또는 mapreduce?

{ 
    date: 'some unix timestamp', 
    total: 12345, 
    paid: true 
} 

내가 열, 매년 행과 전체의 합 개월 (1 월 DEC)와 테이블을 표시해야합니다

나는이 형식의 문서가있는 "송장"컬렉션이 (유료 및 무급으로 나누어 진) 달에. 이처럼 :

 |  Jan  |  Feb  | ... 
2013 | 1,222/200 | 175/2,122 | ... 
... 

당신은 나를 몽고 명령을 제대로 도와 드릴까요? 어쩌면 몽고에서 실행할 수있는 JS 코드를 작성하는 것이 낫겠습니까?

+0

나는 가혹한 것을 의미하지는 않지만, 직접 작성하고 커뮤니티에 당신을 위해 작성하도록 요청하지 않고 세부 사항에 대한 도움을 요청하면 더 잘 작동합니다. 자체 컬렉션에 결과를 저장하지 않으려면 집계 프레임 워크부터 시작하십시오. – JohnnyHK

+0

@ JohnnHK, 전적으로 동의합니다. 저는 정말 배우기에 굉장히 많은 사람입니다. 기본 문법 만 알면 괜찮은 예를 찾을 수 없습니다. 그동안 나는 내 자신의 대답으로 결과를 얻는 뭔가를 얻었다. 이제는 다른 접근법, 어쩌면 집합으로이 작업을 수행해야하는지 여부가 문제입니다. mapreduce 구문이 매우 간단하고 간단합니다. –

+0

mapreduce 구문이 마음에 든다면 성능이 적절하지 않은 경우에만 사용하십시오. 일반적으로 집계 프레임 워크가 빠릅니다. – JohnnyHK

답변

4

이제 MapReduce를 사용하여 해결책을 찾았습니다. PHP에서 사용 중입니다.

$map = new MongoCode(' 
    function() { 
     var d = new Date(this.date*1000); 
     emit({y: d.getFullYear(), m: d.getMonth()}, { 
      total: this.total, 
      notPaid: this.paid ? 0 : this.total, 
      count: 1 
     }); 
    }; 
'); 

$reduce = new MongoCode(' 
    function(month, values) { 
     result = { total: 0, notPaid: 0, count: 0 }; 
     for (var i = 0; i < values.length; i++) { 
      result.total += values[i].total; 
      result.notPaid += values[i].notPaid; 
      result.count += values[i].count; 
     } 
     return result; 
    }; 
'); 

$result = $db->command(array(
    'mapreduce' => 'invoices', 
    'map' => $map, 
    'reduce' => $reduce, 
    'out' => 'temp' 
)); 

echo $result['timeMillis']; 

이제는 결과가 "temp"컬렉션에 있습니다. 한 달에 하나의 문서입니다. 최적화 또는 향상 될 수 있습니까?

db.invoices.aggregate([ 
    { 
     "$project" : { 
      "yr" : { 
       "$year" : "$date" 
      }, 
      "mo" : { 
       "$month" : "$date" 
      }, 
      "total" : 1, 
      "unpaid" : { 
       "$cond" : [ 
        "$paid", 
        0, 
        "$total" 
       ] 
      } 
     } 
    }, 
    { 
     "$group" : { 
      "_id" : { 
       "y" : "$yr", 
       "m" : "$mo" 
      }, 
      "total" : { 
       "$sum" : "$total" 
      }, 
      "unpaid" : { 
       "$sum" : "$unpaid" 
      } 
     } 
    } 
]) 

당신은에 꽤 최대 출력 끝에서 다른 $project를 사용할 수 있으며, $sort은 주문,하지만 그건의 기본 기능의 핵심입니다 :

+0

+1 좋아 보인다. 잘 했어! – JohnnyHK

+0

map/reduce를 통해이를 해결하는 훌륭한 예입니다. 집계 프레임 워크 솔루션에 대한 내 대답을보십시오 (훨씬 빠를 것입니다). –

3

이 같은 통합 프레임 워크를 사용하여이 작업을 수행 할 수 그것.

+0

감사합니다. 왜 mapreduce보다 빠릅니까? 그리고 유닉스 타임 스탬프처럼 날짜를 가진 나와 함께 예제를 사용할 수 있습니까? –

+0

현재 집계 프레임 워크 $ project는 long long으로 저장된 유닉스 타임 스탬프를 직접 date 타입 ($ year과 $ month가 기대하는 것)으로 직접 변환하는 것을 지원하지 않는다. 여전히 $ {cond : [{$ lt : "$ date", ISODate ("2012-01-02T00 : 00 : 00")}을 사용하여 $ 프로젝트를 사용해야합니다. valueOf()}, "Jan-2012", {$ cond : ... etc} ... 모든 타임 스탬프 범위를 적절한 "Year-month"문자열로 매핑하여 그룹화 할 수 있습니다. –

+2

map/reduce보다 훨씬 빠릅니다. 서버에서 기본적으로 실행되기 때문에 map reduce는 JavaScript 셸을 생성하여 코드를 실행하고 다른 것들 중에서 BSON에서 JSON으로 데이터를 변환해야합니다. –

관련 문제