2012-04-02 2 views
4

mapreduce과 관련된 몇 가지 문제점이 있습니다.그룹화, 정렬 및 정렬 값을 줄이는 방법

컬렉션의 일부 값을 그룹화하고 정렬하고 집계하고 싶습니다. 내가 item_id로 그룹화 할과 같은 결과를 각 항목에 대한 각 항목 종류의 날짜를 하루 날짜를 계산 얻을

---------------------------- 
| item_id | date  | 
---------------------------- 
| 1   | 01/15/2012 | 
---------------------------- 
| 2   | 01/01/2012 | 
---------------------------- 
| 1   | 01/15/2012 | 
---------------------------- 
| 1   | 01/01/2012 | 
---------------------------- 
| 2   | 01/03/2012 | 
---------------------------- 
| 2   | 01/03/2012 | 
---------------------------- 
| 1   | 01/01/2012 | 
---------------------------- 
| 1   | 01/01/2012 | 
---------------------------- 
| 2   | 01/01/2012 | 
---------------------------- 
| 2   | 01/01/2012 | 
---------------------------- 

: 나는 mapReduce를 사용

value: {{item_id:1, date:{01/01/2012:3, 01/15/2012:2 }},{item_id:2, date:{01/01/2012:3, 01/03/2012:2 }}} 

내가 수집 등이 있습니다

m=function() 
{ 
    emit(this.item_id, this.date); 
} 
r=function(key, values) 
{ 
var res={}; 
values.forEach(function(v) 
{ 
if(typeof res[v]!='undefined') ? res[v]+=1 : res[v]=1; 
}); 
return res; 
} 

하지만이 같은 결과를받지 않은 :

{{item_id:1, date:{01/01/2012:3, 01/15/2012:2 }},{item_id:2, date:{01/01/2012:3, 01/03/2012:2 }}} 

아이디어가 있으십니까? 형태의

답변

2

을 감안할 때 입력 문서 : 희망 위의 당신이 그것을 필요로 무엇을 할 것인가

var map = function(){ 
    myDate = this.date; 
    var value = {"item_id":this.item_id, "date":{}}; 
    value.date[myDate] = 1; 
    emit(this.item_id, value); 
} 

var reduce = function(key, values){ 
    output = {"item_id":key, "date":{}}; 
    for(v in values){ 
     for(thisDate in values[v].date){ 
      if(output.date[thisDate] == null){ 
       output.date[thisDate] = 1; 
      }else{ 
       output.date[thisDate] += values[v].date[thisDate]; 
      } 
     } 
    } 
    return output; 
} 

> db.runCommand({"mapReduce":"dates", map:map, reduce:reduce, out:{replace:"dates_output"}}) 

> db.dates_output.find() 
{ "_id" : 1, "value" : { "item_id" : 1, "date" : { "1/15/2012" : 2, "1/01/2012" : 3 } } } 
{ "_id" : 2, "value" : { "item_id" : 2, "date" : { "1/01/2012" : 3, "1/03/2012" : 2 } } } 

:

> db.dates.findOne() 
{ "_id" : 1, "item_id" : 1, "date" : "1/15/2012" } 
> 

다음지도와 당신이 찾고있는 출력을 생성한다 기능을 감소 또는 적어도 올바른 방향으로 향하게하십시오. http://www.mongodb.org/display/DOCS/MapReduce

몇 가지 추가지도가 MongoDB를 요리 책에서 예를 줄일 수 있습니다 : 들어 http://cookbook.mongodb.org/

스텝 부산물

지도 MongoDB를 함께 줄 사용에 대한 자세한 내용은

는 몽고의 문서를 참조하십시오 MongoDB 요리 책 레시피의 "추가 정보"섹션을 참조하십시오. http://cookbook.mongodb.org/patterns/finding_max_and_min/

행운을 빌어 요! 행운을 빌어 요!

+0

마크, 도움에 감사드립니다. 이 후에 정렬 날짜에 문제가 있습니다. { "_id": 1, "value": { "item_id": 1, "date": { "1/01/2012": 3, "1/15/2012": 2}}} . 나는 db.runCommand ({ "mapReduce": "dates", map : map, reduce : reduce, sort : {date : 1}, out : {replace : "dates_output"}})에 정렬을 추가했다. . 하지만이 작업을 마친 후에는 { "_id": 1, "value": { "item_id": 1, "date": { "1/01/2012": 1, "1/15/2012": 1} }} 날짜는 정렬이지만 항상 1입니다. –

+0

안녕하세요. 내가 도울 수있어서 기쁩니다! "value"안에 포함 된 요소는 발견 된 순서대로 추가됩니다. 날짜 키의 입력을 정렬하면 임베디드 문서의 날짜가 순서대로 정렬됩니다. 그러나이 예제에서 날짜는 문자열이며 나중에 날짜가있는 문자열의 값이 이전 값의 문자열보다 더 높다는 보장이 없습니다. 예를 들어 (js 셸에서) : > "10/01/2012"< "1/01/2013" false 문자열을 제대로 비교하려면 문자열을 먼저 날짜로 변환해야합니다. – Marc

+0

이것을 처리하면 원하는 순서대로 결과를 얻을 수 있습니다. > db.runCommand ({ "mapReduce": "dates", map : map, reduce : reduce, sort : { "예외 : 쿼리에서 커서를 test.dates에서 만들 수 없습니다."와 유사한 오류가 발생하는 경우 "날짜"필드에 인덱스를 추가해보십시오. "날짜": 1}, out : {replace : "dates_output" 입력 컬렉션의 키. – Marc

관련 문제