문서 메뉴
문서 홈
/
MongoDB 매뉴얼
/ / /

db.collection.mapReduce()

이 페이지의 내용

  • 구문
  • 출력
  • 제한 사항
  • 추가 정보

참고

맵 리듀스의 대안으로서의 집계 파이프라인

MongoDB 5 부터 시작.0 맵 리듀스 는 더 이상 사용되지 않습니다.

맵 리듀스 대안으로서의 애그리게이션 파이프라인 예시는 다음을 참조하세요.

db.collection.mapReduce(map,reduce, { <options> })

중요

Mongo쉬 방법

이 페이지에서는 mongosh 메서드를 설명합니다. 이는 데이터베이스 명령 또는 Node.js와 같은 언어별 드라이버에 대한 설명서가 아닙니다.

데이터베이스 명령에 대해서는 mapReduce 명령을 참조하십시오.

MongoDB API 드라이버의 경우 언어별 MongoDB 드라이버 설명서를 참조하세요.

레거시 mongo 셸 문서는 해당 MongoDB 서버 릴리스 문서를 참조하세요.

Mongo 셸 V4.4

참고

뷰는 맵 축소 작업을 지원하지 않습니다.

참고

MongoDB는 자세한 정보 표시 옵션을 무시합니다.

버전 4.2부터 MongoDB는 다음을 더 이상 사용하지 않습니다.

  • 새 샤드 컬렉션을 생성하는 맵 리듀스 옵션은 물론 맵 리듀스를 위한 샤딩 옵션도 사용합니다. 샤드 컬렉션으로 출력하려면 먼저 샤드 컬렉션을 생성하세요. 게다가 MongoDB 4.2는 기존 샤드 컬렉션의 교체를 더 이상 지원하지 않습니다.

db.collection.mapReduce() 의 구문은 다음과 같습니다:

db.collection.mapReduce(
<map>,
<reduce>,
{
out: <collection>,
query: <document>,
sort: <document>,
limit: <number>,
finalize: <function>,
scope: <document>,
jsMode: <boolean>,
verbose: <boolean>,
bypassDocumentValidation: <boolean>
}
)

db.collection.mapReduce() 다음 매개변수를 사용합니다.

매개 변수
유형
설명
map
JavaScript 또는 문자열

valuekey에 연결하거나 '매핑'하고 key 및 값 pair를 방출하는 JavaScript 함수입니다. 함수를 BSON types JavaScript(BSON Type 13) 또는 문자열(BSON Type 2)로 지정할 수 있습니다.

자세한 내용은 지도 기능의 요구 사항을 참고하세요.

reduce
JavaScript 또는 문자열

특정 key와 연관된 모든 values를 단일 객체로 '줄이는' JavaScript 함수입니다. 함수를 BSON types JavaScript(BSON Type 13) 또는 문자열(BSON Type 2)로 지정할 수 있습니다.

자세한 내용은 리듀스 함수의 요구 사항을 참조하세요.

options
문서
db.collection.mapReduce()에 추가 매개 변수를 지정하는 문서입니다.

다음 표에서는 db.collection.mapReduce()가 수락할 수 있는 추가 인수에 대해 설명합니다.

필드
유형
설명
out
문자열 또는 문서

맵 리듀스 작업 결과의 위치를 지정합니다. collection으로 출력하거나, 조치를 사용하여 collection으로 출력하거나, 인라인으로 출력할 수 있습니다. 세트의 프라이머리 노드에 대해 맵 리듀스 작업을 수행할 때 collection에 출력할 수 있습니다. 세컨더리 노드에서는 inline 출력만 사용할 수 있습니다.

자세한 내용은 out 옵션을 참조하세요.

query
문서
map 함수에 입력된 문서를 결정하기 위해 쿼리 연산자를 사용하여 선택 기준을 지정합니다.
sort
문서
입력 문서를 정렬합니다. 이 옵션은 최적화에 유용합니다. 예를 들어 정렬 키를 내보내기 키와 동일하게 지정하여 축소 작업을 줄이도록 할 수 있습니다. 정렬 키는 이 컬렉션의 기존 인덱스에 있어야 합니다.
limit
숫자
map 함수에 입력할 수 있는 최대 문서 수를 지정합니다.
finalize
JavaScript 또는 문자열

선택 사항입니다. reduce 함수 이후의 출력을 수정하는 JavaScript 함수입니다. 함수를 BSON types JavaScript(BSON Type 13) 또는 문자열(BSON Type 2)로 지정할 수 있습니다.

자세한 내용은 finalize 함수 요구 사항을 참조하세요.

scope
문서
map, reducefinalize 함수에서 액세스할 수 있는 글로벌 변수를 지정합니다.
jsMode
부울

map 함수와 reduce 함수 실행 사이에 중간 데이터를 BSON 형식으로 변환할지 여부를 지정합니다.

기본값은 false입니다.

false인 경우:

  • 내부적으로 MongoDB는 map 함수에서 내보낸 JavaScript 객체를 BSON 객체로 변환합니다. 그러면 이러한 BSON 객체는 reduce 함수를 호출할 때 JavaScript 객체로 다시 변환됩니다.

  • 맵 리듀스 작업은 중간 BSON 객체를 임시 디스크 상의 저장소에 배치합니다. 이를 통해 맵 리듀스 작업을 임의로 큰 데이터 세트에 대해 실행할 수 있습니다.

true인 경우:

  • 내부적으로 map 함수 중에 방출된 JavaScript 객체는 JavaScript 객체로 남아 있습니다. reduce 함수에 대한 객체를 변환할 필요가 없으므로 실행 속도가 빨라질 수 있습니다.

  • 매퍼의 emit() 함수에 대한 고유 key 인수가 500,000개 미만인 결과 세트에만 jsMode를 사용할 수 있습니다.

verbose
부울

결과 정보에 timing 정보를 포함할지 여부를 지정합니다. timing 정보를 포함하려면 verbosetrue로 설정합니다.

기본값은 false입니다.

MongoDB 4.4부터는 이 옵션이 무시됩니다. 결과 정보에는 항상 timing 정보가 제외됩니다. "executionStats" 또는 "allPlansExecution"verbosity 모드에서 db.collection.mapReduce()와 함께 db.collection.explain()을 실행하면 타이밍 정보를 볼 수 있습니다.

collation
문서

선택 사항.

작업에 사용할 데이터 정렬을 지정합니다.

데이터 정렬을 사용하면 대소문자 및 악센트 표시 규칙과 같은 문자열 비교에 대한 언어별 규칙을 지정할 수 있습니다.

데이터 정렬 옵션의 구문은 다음과 같습니다:

collation: {
locale: <string>,
caseLevel: <boolean>,
caseFirst: <string>,
strength: <int>,
numericOrdering: <boolean>,
alternate: <string>,
maxVariable: <string>,
backwards: <boolean>
}

데이터 정렬을 지정할 때 locale 필드는 필수이고, 다른 데이터 정렬 필드는 모두 선택 사항입니다. 필드에 대한 설명은 데이터 정렬 문서를 참조하세요.

데이터 정렬이 지정되지 않았지만 컬렉션에 기본 데이터 정렬이 있는 경우( db.createCollection() 참조), 작업은 컬렉션에 지정된 데이터 정렬을 사용합니다.

컬렉션 또는 연산에 대한 데이터 정렬이 지정되지 않은 경우, MongoDB는 이전 버전에서 문자열 비교에 사용된 간단한 이진 비교를 사용합니다.

한 연산에 대해 여러 데이터 정렬을 지정할 수 없습니다. 예를 들어 필드별로 서로 다른 데이터 정렬을 지정할 수 없으며 정렬과 함께 찾기를 수행하는 경우 찾기 와 정렬에서 각각 다른 데이터 정렬을 사용하는 것은 허용되지 않습니다.

bypassDocumentValidation
부울
선택 사항. mapReduce가 작업 중에 문서 유효성 검사를 우회할 수 있도록 합니다. 이를 통해 유효성 검사 요구 사항을 충족하지 않는 문서를 삽입할 수 있습니다.

참고

map-reduce operations$where 연산자 표현식은 mongosh에서 사용할 수 있는 db와 같은 특정 글로벌 함수 또는 속성에 액세스할 수 없습니다.

$where 및 연산자 map-reduce operations 표현식에 다음 JavaScript 함수 및 속성을 사용할 수 있습니다.

사용 가능한 속성
사용 가능한 기능
args
MaxKey
MinKey
assert()
BinData()
DBPointer()
DBRef()
doassert()
emit()
gc()
HexData()
hex_md5()
isNumber()
isObject()
ISODate()
isString()
Map()
MD5()
NumberInt()
NumberLong()
ObjectId()
print()
printjson()
printjsononeline()
sleep()
Timestamp()
tojson()
tojsononeline()
tojsonObject()
UUID()
version()

map 함수는 각 입력 문서를 0개 이상의 문서로 변환하는 역할을 합니다. scope 매개변수에 정의된 변수에 액세스할 수 있으며 다음과 같은 프로토타입이 있습니다.

function() {
...
emit(key, value);
}

map 함수에는 다음과 같은 요구 사항이 있습니다.

  • map 함수에서 현재 문서를 함수 내의 this로 참조합니다.

  • map 함수는 어떤 이유로든 데이터베이스에 액세스해서는 안됩니다.

  • map 함수는 순수해야 하거나 함수 외부에 영향을 미치지 않아야 합니다(예: 부작용).

  • map 함수는 선택적으로 emit(key,value)를 여러 번 호출하여 keyvalue를 연결하는 출력 문서를 생성할 수 있습니다.

다음 map 함수는 입력 문서의 status 필드 값에 따라 emit(key,value)를 0회 또는 1회 호출합니다.

function() {
if (this.status == 'A')
emit(this.cust_id, 1);
}

다음 map 함수는 입력 문서의 items 필드에 있는 요소 수에 따라 emit(key,value)를 여러 번 호출할 수 있습니다.

function() {
this.items.forEach(function(item){ emit(item.sku, 1); });
}

reduce 함수의 프로토타입은 다음과 같습니다.

function(key, values) {
...
return result;
}

reduce 함수는 다음과 같은 동작을 나타냅니다.

  • reduce 함수는 읽기 작업을 수행하는 경우에도 데이터베이스에 액세스해서는 안됩니다.

  • reduce 함수는 외부 시스템에 영향을 주어서는 안됩니다.

  • MongoDB는 동일한 키에 대해 reduce 함수를 두 번 이상 호출할 수 있습니다. 이 경우 해당 키에 대한 reduce 함수의 이전 출력은 해당 키에 대한 다음 reduce 함수 호출에 대한 입력 값 중 하나가 됩니다.

  • reduce 함수는 scope 매개변수에 정의된 변수에 액세스할 수 있습니다.

  • reduce에 대한 입력은 MongoDB의 최대 BSON 문서 크기 절반보다 크지 않아야 합니다. 큰 문서가 반환된 후 후속 reduce 단계에서 함께 결합되면 이 요구 사항을 위반할 수 있습니다.

동일한 키에 대해 reduce 함수를 두 번 이상 호출할 수 있으므로 다음 속성이 참이여야 합니다.

  • 반환 객체의 유형map 함수에서 방출한 value의 유형과 동일해야 합니다.

  • reduce 함수는 연관성이 있어야 합니다. 다음 설명이 참이어야 합니다.

    reduce(key, [ C, reduce(key, [ A, B ]) ] ) == reduce( key, [ C, A, B ] )
  • reduce 함수는 멱등성이 있어야 합니다. 다음 설명이 참이어야 합니다.

    reduce( key, [ reduce(key, valuesArray) ] ) == reduce( key, valuesArray )
  • reduce 함수는 가환적이어야 합니다. 즉, valuesArray 요소의 순서가 reduce 함수의 출력에 영향을 주지 않아야 하므로 다음 명령문이 참이어야 합니다.

    reduce( key, [ A, B ] ) == reduce( key, [ B, A ] )

out 매개변수에 대해 다음 옵션을 지정할 수 있습니다.

이 옵션은 새 컬렉션으로 출력되며 복제본 세트의 세컨더리 노드에서는 사용할 수 없습니다.

out: <collectionName>

참고

버전 4.2부터 MongoDB는 다음을 더 이상 사용하지 않습니다.

  • 새 샤드 컬렉션을 생성하는 맵 리듀스 옵션은 물론 맵 리듀스를 위한 샤딩 옵션도 사용합니다. 샤드 컬렉션으로 출력하려면 먼저 샤드 컬렉션을 생성하세요. 게다가 MongoDB 4.2는 기존 샤드 컬렉션의 교체를 더 이상 지원하지 않습니다.

이 옵션은 out에 이미 존재하는 컬렉션을 전달할 때만 사용할 수 있습니다. 복제본 세트의 세컨더리 노드는 이 기능을 사용할 수 없습니다.

out: { <action>: <collectionName>
[, db: <dbName>]
[, sharded: <boolean> ] }

작업을 사용하여 컬렉션에 출력하는 경우 out에는 다음과 같은 매개변수가 있습니다.

  • <action>: 다음 작업 중 하나를 지정합니다.

    • replace

      <collectionName>이 있는 컬렉션이 있는 경우 <collectionName>의 내용을 바꿉니다.

    • merge

      출력 컬렉션이 이미 존재하는 경우 새 결과를 기존 결과와 병합합니다. 기존 문서에 새 결과와 동일한 키가 있는 경우 해당 기존 문서를 덮어씁니다.

    • reduce

      출력 컬렉션이 이미 존재하는 경우 새 결과를 기존 결과와 병합합니다. 기존 문서에 새 결과와 동일한 키가 있는 경우 새 문서와 기존 문서 모두에 reduce 함수를 적용하고 결과로 기존 문서를 덮어씁니다.

  • db:

    선택 사항입니다. 맵 리듀스 작업으로 출력을 기록할 데이터베이스의 이름입니다. 기본적으로 이 데이터베이스는 입력 컬렉션과 동일한 데이터베이스가 됩니다.

메모리에서 맵 리듀스 연산을 수행하고 결과를 반환합니다. 이 옵션은 복제본 세트의 세컨더리 노드에서 out에 대해 사용할 수 있는 유일한 옵션입니다.

out: { inline: 1 }

결과는 BSON 문서의 최대 크기에 맞아야 합니다.

finalize 함수의 프로토타입은 다음과 같습니다.

function(key, reducedValue) {
...
return modifiedObject;
}

finalize 함수는 인수로 reduce 함수의 key 값과 reducedValue를 받습니다. 다음 사항에 유의하세요.

  • finalize 함수는 어떤 이유로든 데이터베이스에 액세스해서는 안됩니다.

  • finalize 함수는 순수해야 하거나 함수 외부에 영향을 미치지 않아야 합니다(예: 부작용).

  • finalize 함수는 scope 매개변수에 정의된 변수에 액세스할 수 있습니다.

이 섹션의 예제는 사용자 지정 집계 표현식이 없는 집계 파이프라인 대안을 제시합니다.사용자 정의 표현식을 사용하는 대안에 대해서는 맵 리듀스에서 집계 파이프라인으로 변환 예제를 참조하세요.

이 문서로 샘플 컬렉션 orders을 만드세요.

db.orders.insertMany([
{ _id: 1, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-01"), price: 25, items: [ { sku: "oranges", qty: 5, price: 2.5 }, { sku: "apples", qty: 5, price: 2.5 } ], status: "A" },
{ _id: 2, cust_id: "Ant O. Knee", ord_date: new Date("2020-03-08"), price: 70, items: [ { sku: "oranges", qty: 8, price: 2.5 }, { sku: "chocolates", qty: 5, price: 10 } ], status: "A" },
{ _id: 3, cust_id: "Busby Bee", ord_date: new Date("2020-03-08"), price: 50, items: [ { sku: "oranges", qty: 10, price: 2.5 }, { sku: "pears", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 4, cust_id: "Busby Bee", ord_date: new Date("2020-03-18"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 5, cust_id: "Busby Bee", ord_date: new Date("2020-03-19"), price: 50, items: [ { sku: "chocolates", qty: 5, price: 10 } ], status: "A"},
{ _id: 6, cust_id: "Cam Elot", ord_date: new Date("2020-03-19"), price: 35, items: [ { sku: "carrots", qty: 10, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 7, cust_id: "Cam Elot", ord_date: new Date("2020-03-20"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 8, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 75, items: [ { sku: "chocolates", qty: 5, price: 10 }, { sku: "apples", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 9, cust_id: "Don Quis", ord_date: new Date("2020-03-20"), price: 55, items: [ { sku: "carrots", qty: 5, price: 1.0 }, { sku: "apples", qty: 10, price: 2.5 }, { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" },
{ _id: 10, cust_id: "Don Quis", ord_date: new Date("2020-03-23"), price: 25, items: [ { sku: "oranges", qty: 10, price: 2.5 } ], status: "A" }
])

orders 컬렉션에서의 맵 리듀스 연산을 수행하여 cust_id별로 그룹화합니다. 그리고 각 cust_id에 대한 price의 합계를 계산하세요.

  1. 각 입력 문서를 처리할 맵 함수를 다음과 같이 정의하세요.

    • 이 함수에서 this는 맵 리듀스 작업이 처리하고 있는 문서를 나타냅니다.

    • 이 함수는 각 문서에 대해 pricecust_id에 매핑하고 cust_idprice을 출력합니다.

    var mapFunction1 = function() {
    emit(this.cust_id, this.price);
    };
  2. 두 개의 인수 keyCustIdvaluesPrices을 사용하여 상응하는 리듀스 함수를 정의하세요.

    • valuesPrices는 맵 함수에서 발생한 price 값들로 구성된 배열이며, 이 값들은 keyCustId로 그룹화되어 있습니다.

    • 이 함수는 valuesPrice 배열을 해당 요소의 합으로 리듀스합니다.

    var reduceFunction1 = function(keyCustId, valuesPrices) {
    return Array.sum(valuesPrices);
    };
  3. mapFunction1 맵 함수와 reduceFunction1 리듀스 함수를 사용하여 orders 컬렉션의 모든 문서에 대해 맵-리듀스를 수행하세요.

    db.orders.mapReduce(
    mapFunction1,
    reduceFunction1,
    { out: "map_reduce_example" }
    )

    이 연산은 map_reduce_example이라는 컬렉션에 해당 결과를 출력합니다. map_reduce_example 컬렉션이 이미 존재하는 경우 이 연산은 해당 콘텐츠를 이 맵-리듀스 작업의 결과로 바꿉니다.

  4. map_reduce_example 컬렉션을 쿼리하여 결과를 확인합니다.

    db.map_reduce_example.find().sort( { _id: 1 } )

    이 작업은 다음 문서를 반환합니다.

    { "_id" : "Ant O. Knee", "value" : 95 }
    { "_id" : "Busby Bee", "value" : 125 }
    { "_id" : "Cam Elot", "value" : 60 }
    { "_id" : "Don Quis", "value" : 155 }

사용 가능한 집계 파이프라인 연산자를 사용하면 사용자 지정 함수를 정의하지 않고도 맵-리듀스 작업을 다시 작성할 수 있습니다.

db.orders.aggregate([
{ $group: { _id: "$cust_id", value: { $sum: "$price" } } },
{ $out: "agg_alternative_1" }
])
  1. $group 단계는 cust_id으로 그룹화하고 value 필드를 계산합니다 ($sum도 참조하세요). value 필드에는 각 cust_id의 총 price가 포함되어 있습니다.

    이 단계에서는 다음 문서를 다음 단계로 출력합니다.

    { "_id" : "Don Quis", "value" : 155 }
    { "_id" : "Ant O. Knee", "value" : 95 }
    { "_id" : "Cam Elot", "value" : 60 }
    { "_id" : "Busby Bee", "value" : 125 }
  2. 그런 다음 $out은 결과를 agg_alternative_1 컬렉션에 씁니다. $out 대신 $merge를 사용할 수도 있습니다.

  3. agg_alternative_1 컬렉션을 쿼리하여 결과를 확인합니다.

    db.agg_alternative_1.find().sort( { _id: 1 } )

    이 작업은 다음 문서를 반환합니다.

    { "_id" : "Ant O. Knee", "value" : 95 }
    { "_id" : "Busby Bee", "value" : 125 }
    { "_id" : "Cam Elot", "value" : 60 }
    { "_id" : "Don Quis", "value" : 155 }

다음도 참조하세요.

사용자 정의 집계 표현식을 사용하는 대안은 맵-리듀스에서 집계 파이프라인으로 변환 예제를 참조하세요.

다음 예제에서는 ord_date 값이 2020-03-01 이상인 모든 문서에 대한 orders 컬렉션에서의 대한 맵-리듀스 연산을 볼 수 있습니다.

해당 예제에서의 연산은 다음과 같습니다.

  1. item.sku 필드별로 그룹화하고 각 sku에 대해 주문 수와 총 주문 수량을 계산합니다.

  2. sku 값에 대한 주문당 평균 수량을 계산하고 결과를 출력 컬렉션에 병합합니다.

결과를 병합할 때 기존 문서에 새 결과와 동일한 키가 있으면 작업이 기존 문서를 덮어씁니다. 동일한 키를 가진 기존 문서가 없는 경우에는 해당 문서가 삽입됩니다.

예시 단계:

  1. 각 입력 문서를 처리할 맵 함수를 다음과 같이 정의하세요.

    • 이 함수에서 this는 맵 리듀스 작업이 처리하고 있는 문서를 나타냅니다.

    • 함수는 각 항목에 대해 sku를 새로운 value 객체에 연결합니다. 이 객체에는 count1과 주문에 대한 항목 qty가 포함되어 있으며, sku (key 에 저장됨)와 value를 내보냅니다.

    var mapFunction2 = function() {
    for (var idx = 0; idx < this.items.length; idx++) {
    var key = this.items[idx].sku;
    var value = { count: 1, qty: this.items[idx].qty };
    emit(key, value);
    }
    };
  2. 두 개의 인수 keySKUcountObjVals을 사용하여 상응하는 리듀스 함수를 정의하세요.

    • countObjVals 맵 함수가 리듀서 함수에 전달한 그룹화된 keySKU 값에 매핑된 객체를 가지고 있는 배열입니다.

    • 이 함수는 countObjVals 배열을 countqty 필드를 포함하는 단일 객체 reducedValue로 줄입니다.

    • reducedVal 에서 count 필드는 개별 배열 요소의 count 필드 합계를 포함하고 qty 필드는 개별 배열 요소의 qty 필드 합계를 포함합니다.

    var reduceFunction2 = function(keySKU, countObjVals) {
    reducedVal = { count: 0, qty: 0 };
    for (var idx = 0; idx < countObjVals.length; idx++) {
    reducedVal.count += countObjVals[idx].count;
    reducedVal.qty += countObjVals[idx].qty;
    }
    return reducedVal;
    };
  3. 두 개의 인수 keyreducedVal을 사용하여 최종 함수를 정의합니다. 이 함수는 reducedVal 객체를 수정하여 avg라는 계산된 필드를 추가하고 수정된 객체를 반환합니다.

    var finalizeFunction2 = function (key, reducedVal) {
    reducedVal.avg = reducedVal.qty/reducedVal.count;
    return reducedVal;
    };
  4. mapFunction2, reduceFunction2finalizeFunction2 함수를 사용하여 orders 컬렉션에 대해 맵-리듀스 작업을 수행하세요.

    db.orders.mapReduce(
    mapFunction2,
    reduceFunction2,
    {
    out: { merge: "map_reduce_example2" },
    query: { ord_date: { $gte: new Date("2020-03-01") } },
    finalize: finalizeFunction2
    }
    );

    이 작업은 query 필드를 사용하여 ord_datenew Date("2020-03-01") 이상인 문서만 선택합니다. 그런 다음 결과를 컬렉션 map_reduce_example2에 출력합니다.

    map_reduce_example2 컬렉션이 이미 존재하는 경우 작업은 기존 콘텐츠를 이 맵-리듀스 연산의 결과와 병합합니다. 즉, 기존 문서에 새 결과와 동일한 키가 있는 경우 연산은 기존 문서를 덮어씁니다. 동일한 키를 가진 기존 문서가 없는 경우 해당 문서가 삽입됩니다.

  5. map_reduce_example2 컬렉션을 쿼리하여 결과를 확인합니다.

    db.map_reduce_example2.find().sort( { _id: 1 } )

    이 작업은 다음 문서를 반환합니다.

    { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
    { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
    { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
    { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
    { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }

사용 가능한 집계 파이프라인 연산자를 사용하면 사용자 지정 함수를 정의하지 않고도 맵-리듀스 작업을 다시 작성할 수 있습니다.

db.orders.aggregate( [
{ $match: { ord_date: { $gte: new Date("2020-03-01") } } },
{ $unwind: "$items" },
{ $group: { _id: "$items.sku", qty: { $sum: "$items.qty" }, orders_ids: { $addToSet: "$_id" } } },
{ $project: { value: { count: { $size: "$orders_ids" }, qty: "$qty", avg: { $divide: [ "$qty", { $size: "$orders_ids" } ] } } } },
{ $merge: { into: "agg_alternative_3", on: "_id", whenMatched: "replace", whenNotMatched: "insert" } }
] )
  1. $match 단계에서는 ord_datenew Date("2020-03-01") 이상인 문서만 선택합니다.

  2. $unwind 단계에서는 items 배열 필드별로 문서를 세분화하여 각 배열 요소에 대한 문서를 출력합니다. 예를 들면 다음과 같습니다.

    { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 5, "price" : 2.5 }, "status" : "A" }
    { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "apples", "qty" : 5, "price" : 2.5 }, "status" : "A" }
    { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "oranges", "qty" : 8, "price" : 2.5 }, "status" : "A" }
    { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
    { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "pears", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 4, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-18T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 5, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-19T00:00:00Z"), "price" : 50, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
    ...
  3. $group 단계는 items.sku를 기준으로 그룹화하여 각 sku에 대해 다음과 같이 계산합니다.

    • qty 필드. qty 필드는 다음을 포함합니다.
      items.sku에 대한 총 qty ($sum 참조).
    • orders_ids 배열. orders_ids 필드는 다음을 포함합니다.
      items.sku에 대한 고유 주문 _id 배열 ($addToSet참조).
    { "_id" : "chocolates", "qty" : 15, "orders_ids" : [ 2, 5, 8 ] }
    { "_id" : "oranges", "qty" : 63, "orders_ids" : [ 4, 7, 3, 2, 9, 1, 10 ] }
    { "_id" : "carrots", "qty" : 15, "orders_ids" : [ 6, 9 ] }
    { "_id" : "apples", "qty" : 35, "orders_ids" : [ 9, 8, 1, 6 ] }
    { "_id" : "pears", "qty" : 10, "orders_ids" : [ 3 ] }
  4. $project 단계에서는 맵 리듀스의 출력을 미러링하여 _idvalue 두 필드를 갖도록 출력 문서를 재구성합니다. $project는 다음과 같이 설정합니다.

  5. $unwind 단계에서는 items 배열 필드별로 문서를 세분화하여 각 배열 요소에 대한 문서를 출력합니다. 예를 들면 다음과 같습니다.

    { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 5, "price" : 2.5 }, "status" : "A" }
    { "_id" : 1, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-01T00:00:00Z"), "price" : 25, "items" : { "sku" : "apples", "qty" : 5, "price" : 2.5 }, "status" : "A" }
    { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "oranges", "qty" : 8, "price" : 2.5 }, "status" : "A" }
    { "_id" : 2, "cust_id" : "Ant O. Knee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 70, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
    { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 3, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-08T00:00:00Z"), "price" : 50, "items" : { "sku" : "pears", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 4, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-18T00:00:00Z"), "price" : 25, "items" : { "sku" : "oranges", "qty" : 10, "price" : 2.5 }, "status" : "A" }
    { "_id" : 5, "cust_id" : "Busby Bee", "ord_date" : ISODate("2020-03-19T00:00:00Z"), "price" : 50, "items" : { "sku" : "chocolates", "qty" : 5, "price" : 10 }, "status" : "A" }
    ...
  6. $group 단계는 items.sku를 기준으로 그룹화하여 각 sku에 대해 다음과 같이 계산합니다.

    • qty 필드.qty 필드에는 $sum을 사용하여 계산된 각 items.sku 별 주문된 총 qty가 포함되어 있습니다.

    • orders_ids 배열. orders_ids 필드는 $addToSet을 사용하여 계산된 items.sku의 고유한 주문 _id 배열을 포함하고 있습니다.

    { "_id" : "chocolates", "qty" : 15, "orders_ids" : [ 2, 5, 8 ] }
    { "_id" : "oranges", "qty" : 63, "orders_ids" : [ 4, 7, 3, 2, 9, 1, 10 ] }
    { "_id" : "carrots", "qty" : 15, "orders_ids" : [ 6, 9 ] }
    { "_id" : "apples", "qty" : 35, "orders_ids" : [ 9, 8, 1, 6 ] }
    { "_id" : "pears", "qty" : 10, "orders_ids" : [ 3 ] }
  7. $project 단계에서는 맵 리듀스의 출력을 미러링하여 _idvalue 두 필드를 갖도록 출력 문서를 재구성합니다. $project는 다음과 같이 설정합니다.

    • $size 를 사용하여 value.countorders_ids 배열의 크기로 설정합니다.

    • value.qty를 입력 문서의 qty 필드로 설정합니다.

    • $divide$size를 사용하여 value.avg를 주문당 평균 주문 수량으로 설정합니다.

    { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
    { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }
    { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
    { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
    { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
  8. 마지막으로 $merge는 출력을 컬렉션 agg_alternative_3에 씁니다. 기존 문서에 새 결과와 동일한 키 _id가 있는 경우 작업은 기존 문서를 덮어씁니다. 동일한 키를 가진 기존 문서가 없는 경우 작업이 문서를 삽입합니다.

  9. agg_alternative_3 컬렉션을 쿼리하여 결과를 확인합니다.

    db.agg_alternative_3.find().sort( { _id: 1 } )

    이 작업은 다음 문서를 반환합니다.

    { "_id" : "apples", "value" : { "count" : 4, "qty" : 35, "avg" : 8.75 } }
    { "_id" : "carrots", "value" : { "count" : 2, "qty" : 15, "avg" : 7.5 } }
    { "_id" : "chocolates", "value" : { "count" : 3, "qty" : 15, "avg" : 5 } }
    { "_id" : "oranges", "value" : { "count" : 7, "qty" : 63, "avg" : 9 } }
    { "_id" : "pears", "value" : { "count" : 1, "qty" : 10, "avg" : 10 } }

다음도 참조하세요.

사용자 정의 집계 표현식을 사용하는 대안은 맵-리듀스에서 집계 파이프라인으로 변환 예제를 참조하세요.

db.collection.mapReduce() 메서드의 출력은 mapReduce 명령의 출력과 동일합니다. 출력에 대한 자세한 내용은 mapReduce 명령의 출력 db.collection.mapReduce() 섹션을 참조하세요.

db.collection.mapReduce()는 더 이상 afterClusterTime을 지원하지 않습니다. 따라서 db.collection.mapReduce()인과적으로 일관된 세션과 연결될 수 없습니다.

← db.collection.latencyStats()