Docs Menu

$group (집계)

$group

$group 스테이지는 그룹 키에 따라 동일한 필드, 필드들 또는 표현식을 가진 여러 문서를 단일 문서로 결합합니다. 결과는 고유한 그룹 키당 하나의 문서입니다.

그룹 키는 종종 필드 또는 필드 그룹입니다. 그룹 키는 어떤 표현식의 결과일 수도 있습니다. 그룹 키는 $group 파이프라인 단계의 _id 필드를 사용해 설정할 수 있습니다. 사용 예시는 아래를 참조하세요.

$group 단계 출력에서 _id 필드는 해당 문서의 그룹 키로 설정됩니다.

출력 문서에는 축적자 표현식을 사용하여 설정한 추가 필드도 포함될 수 있습니다.

참고

$group은 출력 문서의 순서를 지정하지 않습니다.

다음 환경에서 호스팅되는 배포에 $group 사용할 수 있습니다.

  • MongoDB Atlas: 클라우드에서의 MongoDB 배포를 위한 완전 관리형 서비스

$group 단계의 프로토타입 형식은 다음과 같습니다.

{
$group:
{
_id: <expression>, // Group key
<field1>: { <accumulator1> : <expression1> },
...
}
}
필드
설명

_id

필수입니다. _id 표현식 그룹 키를 지정합니다. _id null 값 또는 기타 상수 값을 지정하는 경우 $group 단계는 모든 입력 문서의 값을 집계하는 단일 문서 반환합니다. Null로 그룹화 예시 참조하세요.

field

_id누산기 연산자는 유효한 expression을 모두 허용할 수 있습니다. 표현식에 대한 자세한 내용은 표현식 연산자를 참조하세요.

$group 은(는) 차단 단계로, 파이프라인 이 데이터를 처리 하기 전에 차단 단계의 모든 입력 데이터가 검색될 때까지 대기하도록 합니다. 차단 단계는 여러 단계로 구성된 파이프라인 의 병렬 처리 를 줄이기 때문에 성능이 저하될 수 있습니다. 차단 단계는 대규모 데이터 세트에 상당한 양의 메모리를 사용할 수도 있습니다.

<accumulator> 연산자는 다음 누산기 연산자 중 하나이어야 합니다.

버전 5.0에서 변경됨

이름
설명

사용자 정의 누산기 함수의 결과를 반환합니다.

각 그룹에 대한 고유한 표현식 값의 배열을 반환합니다. 배열 요소의 순서가 정의되지 않았습니다.

버전 5.0에서 변경: $setWindowFields 단계에서 사용할 수 있습니다.

숫자 값의 평균을 반환합니다. 숫자가 아닌 값을 무시합니다.

버전 5.0에서 변경: $setWindowFields 단계에서 사용할 수 있습니다.

지정된 정렬 순서에 따라 그룹 내 하위 요소를 반환합니다.

버전 5.2에 추가되었습니다.

2} 및 단계에서 $group $setWindowFields 사용할 수 있습니다.

지정된 정렬 순서에 따라 그룹 내 하위 개 요소의 집계를 반환합니다.n

버전 5.2에 추가되었습니다.

2} 및 단계에서 $group $setWindowFields 사용할 수 있습니다.

그룹에 있는 문서 수를 반환합니다.

$count 파이프라인 스테이지와는 다릅니다.

버전 5.2의 새로운 기능: $group$setWindowFields 단계에서 사용할 수 있습니다.

그룹의 첫 번째 문서에 대한 표현식 결과를 반환합니다.

버전 5.0에서 변경: $setWindowFields 단계에서 사용할 수 있습니다.

그룹 내 첫 n 개 요소의 집계를 반환합니다. 문서가 정해진 순서로 정리되어 있을 때만 의미가 있습니다. $firstN 배열 연산자와 다릅니다.

버전 5.2의 새로운 기능: $group, 표현식, $setWindowFields 단계에서 사용할 수 있습니다.

그룹의 마지막 문서에 대한 표현식의 결과를 반환합니다.

버전 5.0에서 변경: $setWindowFields 단계에서 사용할 수 있습니다.

그룹 내 마지막 n 개 요소의 집계를 반환합니다. 문서가 정해진 순서로 정리되어 있을 때만 의미가 있습니다. $lastN 배열 연산자와 다릅니다.

버전 5.2의 새로운 기능: $group, 표현식, $setWindowFields 단계에서 사용할 수 있습니다.

각 그룹에 대해 가장 높은 표현식 값을 반환합니다.

버전 5.0에서 변경: $setWindowFields 단계에서 사용할 수 있습니다.

그룹 내 최댓값을 가진 개 요소의 집계를 반환합니다.n $maxN 배열 연산자와는 다릅니다.

버전 5.2에 추가되었습니다.

$group, $setWindowFields표현식으로 사용할 수 있습니다.

중앙값, 즉 50번째 백분위수의 근사치를 스칼라 값으로 반환합니다.

버전 7.0에 추가.

이 연산자는 이 단계에서 누산기로 사용할 수 있습니다:

집계 표현식으로도 사용할 수 있습니다.

각 그룹에 대한 입력 문서를 결합하여 생성된 문서를 반환합니다.

각 그룹에 대해 가장 낮은 표현식 값을 반환합니다.

버전 5.0에서 변경: $setWindowFields 단계에서 사용할 수 있습니다.

그룹 내 최솟값을 가진 개 요소의 집계를 반환합니다.n $minN 배열 연산자와 다릅니다.

버전 5.2에 추가되었습니다.

$group, $setWindowFields표현식으로 사용할 수 있습니다.

지정된 백분위수 값에 해당하는 스칼라 값의 배열을 반환합니다.

버전 7.0에 추가.

이 연산자는 이 단계에서 누산기로 사용할 수 있습니다:

집계 표현식으로도 사용할 수 있습니다.

각 그룹의 문서에 대한 표현식 값의 배열을 반환합니다.

버전 5.0에서 변경: $setWindowFields 단계에서 사용할 수 있습니다.

입력 값의 모집단 표준 편차를 반환합니다.

버전 5.0에서 변경: $setWindowFields 단계에서 사용할 수 있습니다.

입력 값의 표본 표준 편차를 반환합니다.

버전 5.0에서 변경: $setWindowFields 단계에서 사용할 수 있습니다.

숫자 값의 합계를 반환합니다. 숫자가 아닌 값을 무시합니다.

버전 5.0에서 변경: $setWindowFields 단계에서 사용할 수 있습니다.

지정된 정렬 순서에 따라 그룹 내 최상위 요소를 반환합니다.

버전 5.2에 추가되었습니다.

2} 및 단계에서 $group $setWindowFields 사용할 수 있습니다.

지정된 정렬 순서에 따라 그룹 내 상위 개 요소의 집계를 반환합니다.n

버전 5.2에 추가되었습니다.

2} 및 단계에서 $group $setWindowFields 사용할 수 있습니다.

$group 단계가 100MB의 RAM을 초과하면 MongoDB는 임시 파일에 데이터를 씁니다. 그러나 allowDiskUse 옵션이 false로 설정되어 있으면 $group은 오류를 반환합니다. 자세한 내용은 집계 파이프라인 제한을 참조하세요.

이 섹션에서는 $group의 성능을 개선하기 위한 최적화에 대해 설명합니다. 수동으로 수행할 수 있는 최적화와 MongoDB가 내부적으로 수행할 수 있는 최적화가 있습니다.

파이프라인이 동일한 필드를 기준으로 sorts(정렬) 및 groups(그룹화)를 수행하고, $group 단계에서 $first 또는 $last 누산기 연산자만 사용하는 경우 정렬 순서와 일치하는 그룹화된 필드에 인덱스 를 추가하는 것이 좋습니다. 어떤 경우에는 $group 단계에서 인덱스를 사용하여 각 그룹의 첫 번째 또는 마지막 문서를 빠르게 찾을 수 있습니다.

예시

foo이라는 컬렉션에 { x: 1, y: 1 } 인덱스가 포함된 경우 다음 파이프라인은 해당 인덱스를 사용하여 각 그룹의 첫 번째 문서를 찾을 수 있습니다.

db.foo.aggregate([
{
$sort:{ x : 1, y : 1 }
},
{
$group: {
_id: { x : "$x" },
y: { $first : "$y" }
}
}
])

참고

버전 7.0.17부터 7.0의 패치 버전에 대해 슬롯 기반 쿼리 실행 엔진 더 이상 기본값 으로 활성화되지 않습니다. 쿼리에서 슬롯 기반 쿼리 실행 엔진 사용하려면 기본값 으로 활성화되어 있는 버전 8.0으로 업그레이드 하세요.

버전 5.2부터는 다음 중 하나에 해당하는 경우 MongoDB가 슬롯 기반 실행 쿼리 엔진을 사용해 $group 단계를 실행합니다.

  • $group은(는) 파이프라인의 첫 번째 단계입니다.

  • 파이프라인의 모든 이전 단계는 슬롯 기반 실행 엔진에 의해 실행될 수도 있습니다.

자세한 내용은 $group 최적화를 참조하세요.

mongosh에서 다음 문서를 사용하여 sales라는 이름의 샘플 컬렉션을 만듭니다.

db.sales.insertMany([
{ "_id" : 1, "item" : "abc", "price" : Decimal128("10"), "quantity" : Int32("2"), "date" : ISODate("2014-03-01T08:00:00Z") },
{ "_id" : 2, "item" : "jkl", "price" : Decimal128("20"), "quantity" : Int32("1"), "date" : ISODate("2014-03-01T09:00:00Z") },
{ "_id" : 3, "item" : "xyz", "price" : Decimal128("5"), "quantity" : Int32( "10"), "date" : ISODate("2014-03-15T09:00:00Z") },
{ "_id" : 4, "item" : "xyz", "price" : Decimal128("5"), "quantity" : Int32("20") , "date" : ISODate("2014-04-04T11:21:39.736Z") },
{ "_id" : 5, "item" : "abc", "price" : Decimal128("10"), "quantity" : Int32("10") , "date" : ISODate("2014-04-04T21:23:13.331Z") },
{ "_id" : 6, "item" : "def", "price" : Decimal128("7.5"), "quantity": Int32("5" ) , "date" : ISODate("2015-06-04T05:08:13Z") },
{ "_id" : 7, "item" : "def", "price" : Decimal128("7.5"), "quantity": Int32("10") , "date" : ISODate("2015-09-10T08:43:00Z") },
{ "_id" : 8, "item" : "abc", "price" : Decimal128("10"), "quantity" : Int32("5" ) , "date" : ISODate("2016-02-06T20:20:13Z") },
])

다음 집계 작업은 $group 단계를 사용하여 sales 컬렉션의 문서 수를 계산합니다.

db.sales.aggregate( [
{
$group: {
_id: null,
count: { $count: { } }
}
}
] )

이 연산은 다음과 같은 결과를 반환합니다.

{ "_id" : null, "count" : 8 }

이 집계 작업은 다음 SQL 문과 동일합니다.

SELECT COUNT(*) AS count FROM sales

다음도 참조하세요.

다음 집계 연산은 $group 단계를 사용하여 sales 컬렉션에서 고유 항목 값을 조회합니다.

db.sales.aggregate( [ { $group : { _id : "$item" } } ] )

이 연산은 다음과 같은 결과를 반환합니다.

{ "_id" : "abc" }
{ "_id" : "jkl" }
{ "_id" : "def" }
{ "_id" : "xyz" }

참고

$group 를 사용하여 샤딩된 컬렉션 에서 고유 값을 조회 할 때 작업 결과 가 발생하면 결과에 DISTINCT_SCAN 고아 문서가포함될 수 있습니다.

영향을 받는 유일한 의미론적으로 올바른 파이프라인 distinct $group 파이프라인 시작 부분에 단계가 있고 앞에 단계가 없는 명령과 사실상 논리적으로 $group $sort 동일합니다. .

예시 들어, 다음 형식의 $group 연산은 DISTINCT_SCAN이(가) 발생할 수 있습니다.

{ $group : { _id : "$<field>" } }

고유 값을 검색하기 위한 동작에 대한 자세한 내용은 고유 명령 동작을 참조하세요.

작업 결과가 인지 DISTINCT_SCAN확인하려면작업의 설명 결과를 확인하세요.

다음 집계 작업은 item 필드를 기준으로 문서를 그룹화하여 품목당 총 판매 금액을 계산하고 총 판매 금액이 100 이상인 품목만 반환합니다.

db.sales.aggregate(
[
// First Stage
{
$group :
{
_id : "$item",
totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } }
}
},
// Second Stage
{
$match: { "totalSaleAmount": { $gte: 100 } }
}
]
)
첫 번째 단계:
$group 단계는 고유 항목 값을 검색하기 위해 문서를 item으로 그룹화합니다. 이 단계에서는 각 항목에 totalSaleAmount를 반환합니다.
두 번째 단계:
$match 단계는 결과 문서를 필터링하여 totalSaleAmount이(가) 100보다 크거나 같은 항목만 반환합니다.

이 연산은 다음과 같은 결과를 반환합니다.

{ "_id" : "abc", "totalSaleAmount" : Decimal128("170") }
{ "_id" : "xyz", "totalSaleAmount" : Decimal128("150") }
{ "_id" : "def", "totalSaleAmount" : Decimal128("112.5") }

이 집계 작업은 다음 SQL 문과 동일합니다.

SELECT item,
Sum(( price * quantity )) AS totalSaleAmount
FROM sales
GROUP BY item
HAVING totalSaleAmount >= 100

다음도 참조하세요.

mongosh에서 다음 문서를 사용하여 sales라는 이름의 샘플 컬렉션을 만듭니다.

db.sales.insertMany([
{ "_id" : 1, "item" : "abc", "price" : Decimal128("10"), "quantity" : Int32("2"), "date" : ISODate("2014-03-01T08:00:00Z") },
{ "_id" : 2, "item" : "jkl", "price" : Decimal128("20"), "quantity" : Int32("1"), "date" : ISODate("2014-03-01T09:00:00Z") },
{ "_id" : 3, "item" : "xyz", "price" : Decimal128("5"), "quantity" : Int32( "10"), "date" : ISODate("2014-03-15T09:00:00Z") },
{ "_id" : 4, "item" : "xyz", "price" : Decimal128("5"), "quantity" : Int32("20") , "date" : ISODate("2014-04-04T11:21:39.736Z") },
{ "_id" : 5, "item" : "abc", "price" : Decimal128("10"), "quantity" : Int32("10") , "date" : ISODate("2014-04-04T21:23:13.331Z") },
{ "_id" : 6, "item" : "def", "price" : Decimal128("7.5"), "quantity": Int32("5" ) , "date" : ISODate("2015-06-04T05:08:13Z") },
{ "_id" : 7, "item" : "def", "price" : Decimal128("7.5"), "quantity": Int32("10") , "date" : ISODate("2015-09-10T08:43:00Z") },
{ "_id" : 8, "item" : "abc", "price" : Decimal128("10"), "quantity" : Int32("5" ) , "date" : ISODate("2016-02-06T20:20:13Z") },
])

다음 파이프라인은 2014년 한 해 동안의 총 판매 금액, 평균 판매량 및 일일 판매 횟수를 계산합니다.

db.sales.aggregate([
// First Stage
{
$match : { "date": { $gte: new ISODate("2014-01-01"), $lt: new ISODate("2015-01-01") } }
},
// Second Stage
{
$group : {
_id : { $dateToString: { format: "%Y-%m-%d", date: "$date" } },
totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } },
averageQuantity: { $avg: "$quantity" },
count: { $sum: 1 }
}
},
// Third Stage
{
$sort : { totalSaleAmount: -1 }
}
])
첫 번째 단계:
$match 단계는 2014년에 작성된 문서만 다음 단계로 전달하도록 문서를 필터링합니다.
두 번째 단계:
$group 단계에서는 문서를 날짜별로 그룹화하고 각 그룹에 있는 문서의 총 판매 금액, 평균 수량 및 총 개수를 계산합니다.
세 번째 단계:
$sort 단계는 각 그룹의 총 판매 금액을 기준으로 결과를 내림차순으로 정렬합니다.

이 연산은 다음과 같은 결과를 반환합니다.

{
"_id" : "2014-04-04",
"totalSaleAmount" : Decimal128("200"),
"averageQuantity" : 15, "count" : 2
}
{
"_id" : "2014-03-15",
"totalSaleAmount" : Decimal128("50"),
"averageQuantity" : 10, "count" : 1
}
{
"_id" : "2014-03-01",
"totalSaleAmount" : Decimal128("40"),
"averageQuantity" : 1.5, "count" : 2
}

이 집계 작업은 다음 SQL 문과 동일합니다.

SELECT date,
Sum(( price * quantity )) AS totalSaleAmount,
Avg(quantity) AS averageQuantity,
Count(*) AS Count
FROM sales
WHERE date >= '01/01/2014' AND date < '01/01/2015'
GROUP BY date
ORDER BY totalSaleAmount DESC

다음도 참조하세요.

다음 집계 작업은 null의 그룹 _id을(를) 지정하여 collection의 총 판매 금액, 평균 수량 및 모든 문서의 개수를 계산합니다.

db.sales.aggregate([
{
$group : {
_id : null,
totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } },
averageQuantity: { $avg: "$quantity" },
count: { $sum: 1 }
}
}
])

이 연산은 다음과 같은 결과를 반환합니다.

{
"_id" : null,
"totalSaleAmount" : Decimal128("452.5"),
"averageQuantity" : 7.875,
"count" : 8
}

이 집계 작업은 다음 SQL 문과 동일합니다.

SELECT Sum(price * quantity) AS totalSaleAmount,
Avg(quantity) AS averageQuantity,
Count(*) AS Count
FROM sales

다음도 참조하세요.

mongosh에서 다음 문서를 사용하여 books라는 이름의 샘플 컬렉션을 만듭니다.

db.books.insertMany([
{ "_id" : 8751, "title" : "The Banquet", "author" : "Dante", "copies" : 2 },
{ "_id" : 8752, "title" : "Divine Comedy", "author" : "Dante", "copies" : 1 },
{ "_id" : 8645, "title" : "Eclogues", "author" : "Dante", "copies" : 2 },
{ "_id" : 7000, "title" : "The Odyssey", "author" : "Homer", "copies" : 10 },
{ "_id" : 7020, "title" : "Iliad", "author" : "Homer", "copies" : 10 }
])

다음 집계 작업은 books collection의 데이터를 피봇하여 작성자별로 제목을 그룹화합니다.

db.books.aggregate([
{ $group : { _id : "$author", books: { $push: "$title" } } }
])

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

{ "_id" : "Homer", "books" : [ "The Odyssey", "Iliad" ] }
{ "_id" : "Dante", "books" : [ "The Banquet", "Divine Comedy", "Eclogues" ] }

다음 집계 작업은 author를 기준으로 문서를 그룹화합니다.

db.books.aggregate([
// First Stage
{
$group : { _id : "$author", books: { $push: "$$ROOT" } }
},
// Second Stage
{
$addFields:
{
totalCopies : { $sum: "$books.copies" }
}
}
])
첫 번째 단계:

$group$ROOT 시스템 변수를 사용하여 전체 문서를 작성자별로 그룹화합니다. 이 단계에서는 다음 문서를 다음 단계로 전달합니다.

{ "_id" : "Homer",
"books" :
[
{ "_id" : 7000, "title" : "The Odyssey", "author" : "Homer", "copies" : 10 },
{ "_id" : 7020, "title" : "Iliad", "author" : "Homer", "copies" : 10 }
]
},
{ "_id" : "Dante",
"books" :
[
{ "_id" : 8751, "title" : "The Banquet", "author" : "Dante", "copies" : 2 },
{ "_id" : 8752, "title" : "Divine Comedy", "author" : "Dante", "copies" : 1 },
{ "_id" : 8645, "title" : "Eclogues", "author" : "Dante", "copies" : 2 }
]
}
두 번째 단계:

$addFields은(는) 각 저자의 총 도서 사본 수를 포함하는 필드를 출력에 추가합니다.

참고

결과 문서는 BSON 문서 크기 제한인 16메비바이트를 초과할 수 없습니다.

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

{
"_id" : "Homer",
"books" :
[
{ "_id" : 7000, "title" : "The Odyssey", "author" : "Homer", "copies" : 10 },
{ "_id" : 7020, "title" : "Iliad", "author" : "Homer", "copies" : 10 }
],
"totalCopies" : 20
}
{
"_id" : "Dante",
"books" :
[
{ "_id" : 8751, "title" : "The Banquet", "author" : "Dante", "copies" : 2 },
{ "_id" : 8752, "title" : "Divine Comedy", "author" : "Dante", "copies" : 1 },
{ "_id" : 8645, "title" : "Eclogues", "author" : "Dante", "copies" : 2 }
],
"totalCopies" : 5
}

다음도 참조하세요.

우편번호 데이터 세트를 사용한 집계 튜토리얼에서는 $group 연산자에 관한 광범위한 일반 사용 사례 예시를 설명합니다.