MongoDB에서 mapReduce() 함수를 활용하면 컬렉션에 저장된 문서 중 원하는 조건에 맞는 문서만 골라낼 수 있습니다. 이 글에서는 scope 변수로 문서 순서를 카운트하고, 대체(홀수 번째) 문서만 emit()으로 내보내는 방법을 단계별로 살펴보겠습니다.
1. 샘플 데이터 준비하기
먼저 데모용 컬렉션을 생성하고 문서를 여러 개 삽입합니다.
> db.demo636.insert({id:1});
WriteResult({ "nInserted" : 1 })
> db.demo636.insert({id:2});
WriteResult({ "nInserted" : 1 })
> db.demo636.insert({id:3});
WriteResult({ "nInserted" : 1 })
> db.demo636.insert({id:4});
WriteResult({ "nInserted" : 1 })
> db.demo636.insert({id:5});
WriteResult({ "nInserted" : 1 })
> db.demo636.insert({id:6});
WriteResult({ "nInserted" : 1 })
2. find()로 전체 문서 확인하기
find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 한눈에 조회할 수 있습니다.
> db.demo636.find();
위 명령을 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : ObjectId("5e9c127b6c954c74be91e6d2"), "id" : 1 }
{ "_id" : ObjectId("5e9c127e6c954c74be91e6d3"), "id" : 2 }
{ "_id" : ObjectId("5e9c127f6c954c74be91e6d4"), "id" : 3 }
{ "_id" : ObjectId("5e9c12816c954c74be91e6d5"), "id" : 4 }
{ "_id" : ObjectId("5e9c12836c954c74be91e6d6"), "id" : 5 }
{ "_id" : ObjectId("5e9c12896c954c74be91e6d7"), "id" : 6 }
총 6개의 문서가 순서대로 저장되어 있는 것을 확인할 수 있습니다.
3. mapReduce()로 대체 문서만 출력하는 쿼리 작성
다음 쿼리는 map 함수 안에서 scope로 전달받은 카운터(oddCounter)를 문서마다 하나씩 증가시키고, 카운터가 2로 나누어 떨어지지 않을 때만 emit()으로 문서를 내보냅니다. 그 결과 첫 번째, 세 번째, 다섯 번째 문서처럼 하나씩 건너뛰며 출력됩니다.
> db.demo636.mapReduce(
... function () {
... oddCounter++;
... var id = this._id;
... delete this._id;
... if ( oddCounter % d != 0 )
... emit(id, this);
... },
... function() {},
... {
... "scope": { "oddCounter": 0, "d": 2 },
... "out": { "inline": 1 }
... }
... )
4. 실행 결과 확인하기
쿼리를 실행하면 아래와 같이 대체 문서(id가 1, 3, 5인 문서)만 results 배열에 담겨 반환됩니다.
{
"results" : [
{
"_id" : ObjectId("5e9c127b6c954c74be91e6d2"),
"value" : {
"id" : 1
}
},
{
"_id" : ObjectId("5e9c127f6c954c74be91e6d4"),
"value" : {
"id" : 3
}
},
{
"_id" : ObjectId("5e9c12836c954c74be91e6d6"),
"value" : {
"id" : 5
}
}
],
"timeMillis" : 29,
"counts" : {
"input" : 6,
"emit" : 3,
"reduce" : 0,
"output" : 3
},
"ok" : 1
}
counts 항목을 보면 input이 6개였지만 emit은 3번만 발생했고, 최종 output 역시 3개인 것을 알 수 있습니다.
핵심 포인트 정리
- scope: map/reduce 함수에서 사용할 전역 변수를 정의합니다. 여기서는 카운터(
oddCounter)와 나눌 값(d = 2)을 초기화했습니다. - emit(key, value): map 단계에서 조건에 맞는 문서를 결과로 내보냅니다. 이 예제에서는 원본
_id를 키로 사용하고,delete this._id로 value에서는 제거했습니다. - out: { inline: 1 }: 결과를 별도 컬렉션에 저장하지 않고 즉시 화면에 출력합니다.
- 응용:
d값을 3으로 바꾸면 세 번째마다 하나씩 출력되도록 조건을 손쉽게 변경할 수 있습니다.
참고로 mapReduce는 MongoDB 5.0부터 집계 파이프라인(aggregation pipeline) 사용이 권장되는 기능이므로, 실무에서는 상황에 따라 $group, $match 등의 연산자를 활용한 대안도 함께 고려해 보시기 바랍니다.