입력 요소에서 두 번째 요소를 집계하려면 mapReduce() 메서드를 활용하면 됩니다. 맵리듀스(Map-Reduce)는 대량의 데이터를 유용한 집계 결과로 압축하는 데이터 처리 패러다임입니다. 이 글에서는 실제 예제를 통해 입력 요소 중 두 번째 요소를 추출·집계하는 과정을 단계별로 살펴보겠습니다.
1. 샘플 컬렉션 생성
먼저 다음과 같이 문서가 포함된 컬렉션을 생성합니다.
> db.demo621.insert({ _id: 101, Name1: "John", Name2: "John" });
WriteResult({ "nInserted" : 1 })
> db.demo621.insert({ _id: 102, Name1: "Bob", Name2: "John" });
WriteResult({ "nInserted" : 1 })
> db.demo621.insert({ _id: 103, Name1: "Chris", Name2: "John" });
WriteResult({ "nInserted" : 1 })
> db.demo621.insert({ _id: 104, Name1: "Sam", Name2: "John" });
WriteResult({ "nInserted" : 1 })2. 컬렉션의 모든 문서 조회
find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 확인할 수 있습니다.
> db.demo621.find();
위 쿼리는 다음과 같은 출력을 생성합니다.
{ "_id" : 101, "Name1" : "John", "Name2" : "John" }
{ "_id" : 102, "Name1" : "Bob", "Name2" : "John" }
{ "_id" : 103, "Name1" : "Chris", "Name2" : "John" }
{ "_id" : 104, "Name1" : "Sam", "Name2" : "John" }3. mapReduce()로 두 번째 요소 집계하기
다음은 입력 요소에서 두 번째 요소를 집계하는 쿼리입니다.
> db.demo621.mapReduce(
... function () {
... track++;
... var actualId= this._id;
... delete this._id;
... if ( track % div == 0 )
... emit(actualId, this );
... },
... function() {},
... {
... "scope": { "track": 0, "div": 2 },
... "out": { "inline": 1 }
... }
... )쿼리 동작 방식
이 쿼리의 핵심은 scope 옵션에 있습니다. scope를 통해 전역 변수 track(카운터, 초기값 0)와 div(나눌 값, 2)를 정의합니다. map 함수가 각 문서마다 실행될 때마다 track이 1씩 증가하며, track % div == 0 조건, 즉 카운터가 2로 나누어 떨어질 때만 emit()을 호출해 해당 문서를 출력합니다. 그 결과 짝수 번째 위치의 문서인 _id: 102(Bob)와 _id: 104(Sam), 즉 두 번째와 네 번째 요소만 최종 결과에 포함됩니다.
위 쿼리는 다음과 같은 출력을 생성합니다.
{
"results" : [
{
"_id" : 102,
"value" : {
"Name1" : "Bob",
"Name2" : "John"
}
},
{
"_id" : 104,
"value" : {
"Name1" : "Sam",
"Name2" : "John"
}
}
],
"timeMillis" : 48,
"counts" : {
"input" : 4,
"emit" : 2,
"reduce" : 0,
"output" : 2
},
"ok" : 1
}출력 결과를 보면 counts 항목에서 input이 4, emit이 2, output이 2로 나타나는데, 이는 4개의 입력 문서 중 절반인 2개의 문서만 방출(emit)되어 최종 출력되었음을 의미합니다.