[MongoDB] Aggregate 집계
MongoDB
→ 집계 처리. 그 중 Aggregate에 대하여
Aggregate
기본적인 스테이지 종류
-
$project : 어떤 해당필드의 값을 어떻게 표현할지 결정하는 스테이지
db.rating.aggregate([ { $project : {_id:0, rating: 1, hello: "new field"} <- hello는 새로운 필드 } ]) ↓↓↓ 결과 ↓↓↓ {"rating" : 1, "hello" : "new field"} {"rating" : 2, "hello" : "new field"} {"rating" : 3, "hello" : "new field"} {"rating" : 3, "hello" : "new field"} {"rating" : 4, "hello" : "new field"} {"rating" : 4, "hello" : "new field"} {"rating" : 5, "hello" : "new field"} {"rating" : 5, "hello" : "new field"} {"rating" : 5, "hello" : "new field"} {"rating" : 5, "hello" : "new field"} // 곱셈도 가능 db.rating.aggregate([ { $project : { _id : 0, multiply : {$multiply: ["$_id","$user_id"]} } } ]) ↓↓↓ 결과 ↓↓↓ {"multiply" : 2} {"multiply" : 6} {"multiply" : 12}
-
$group : _id 값에 그룹화의 기준이 되는 값 설정 필요
db.rating.aggregate([ { $group: {_id : "$rating", count: {$sum : 1}} } ])
-
$match : 앞서 배운 query 부분과 동일한 역할
db.rating.aggreagate([ { $match : {rating : {$gte : 4}} }, { $group : {_id : "$rating", user_ids : {$push : "$user_id"}} } ]) ↓↓↓ 결과 ↓↓↓ {"_id" : 5, "user_ids" : [11,12,10,9]} {"_id" : 4, "user_ids" : [8, 5]}
-
$unwind : 하나의 도큐먼트에 들어있는 배열 요소들을 각각의 도큐먼트로 만드는 기능 (SQL 식으로 설명하자면 배열에 들어있는 값을 각각의 row로 분리하는 기능)
※ 위의 match 샘플 코드에 unwind만 적용했을 때 결과값에 주목 db.rating.aggreagate([ { $match : {rating : {$gte : 4}} }, { $group : {_id : "$rating", user_ids : {$push : "$user_id"}} }, { $unwind : "$user_ids" } ]) ↓↓↓ 결과 ↓↓↓ {"_id" 5: , "user_ids" : 11} {"_id" 5: , "user_ids" : 12} {"_id" 5: , "user_ids" : 10} {"_id" 5: , "user_ids" : 9} {"_id" 4: , "user_ids" : 8} {"_id" 4: , "user_ids" : 5}
-
$out : 입력받은 도큐먼트를 out필드의 값으로 지정한 이름의 컬렉션에 저장하는 역할
db.rating.aggreagate([ { $group : {_id : "$rating", user_ids : {$push : "$user_id"}} }, { $out : "user_ids_by_rating" } ])
이 경우, 결과값을 “user_ids_by_rating”라는 컬렉션에 저장.
맵-리듀스에서는 컬렉션에 저장할 때 덮어쓰는 방식 외에도 기존의 컬렉션에 도큐먼트를 추가하는 방식이 있었지만 집계 파이프라인은 해당 기능이 없다는 점 참고.
입력도큐먼트 제어 스테이지
- $limit :
{ $limit : <number> }
- $skip : 입력받은 도큐먼트(결과값 도큐먼트) 중 지정된 숫자만큼 건너뛰고 출력.
{ $skip : <number> }
- $sort :
{ $limit : <number> }
( ※ 처리하는 도큐먼트의 총 크기가 100MB를 넘을 수 없음. 100MB 이상의 용량을 가진 도큐먼트들을 정렬하고자 할 때에는{allowDiskUse : true}
옵션 추가필요)
고급스테이지 (164p)
- $bucket : 범위에 따라 그룹화하는 기능
db.rating.aggregate([ { $bucket : { groupby : "$rating", boundaries : [2, 3, 5], default : "Others", output : { count : {$sum : 1}, user_ids : {$push : "$user_id"} } } } ]) {"_id" : 2, "count" : 1, "user_ids" : [3]} {"_id" : 3, "count" : 4, "user_ids" : [4, 1, 5, 8]} {"_id" : "Others", "count" : 1, "user_ids" : [2, 9, 10 ,11, 12]}
- groupby 파라미터 > “rating”필드를 기준으로 그룹화
- boundaries 파라미터 > 범위를 지정
위의 예시는 “2이상 3미만”, “3이상 5미만” 두 구간으로 나누겠다고 설정하였고,
2이상 3미만 범위 내 도큐먼트들은 “_id” : 2 에 그룹화된 결과. - default 파라미터 > (선택) 정한 구간 외 도큐먼트를 모을 필드명 지정
- output 파라미터 > (선택) 그룹화를 하고 난 후 출력 결과를 어떻게 표시할지 결정
- $addFields : 필드를 추가하는 기능
db.rating.aggregate([ { $addFields : { hello : "world" } }, { $project : { hello : 1} }, { $limit : 3 } ]) {"_id" : 1, "hello" : "world"} {"_id" : 2, "hello" : "world"} {"_id" : 3, "hello" : "world"}
addFields를 통해 추가한 필드가 이미 존재하고있다면 덮어쓰기가 된다.
이 스테이지와 점 연산자를 이용하면 임베디드 도큐먼트에도 필드 추가 가능db.rating.aggregate([ { $addFields : { "hi.hello" : "world" } }, { $project : { hi : {hello : 1} } }, { $limit : 3 } ]) {"_id" : 1, "hi" : {"hello" : "world"} } {"_id" : 2, "hi" : {"hello" : "world"} } {"_id" : 3, "hi" : {"hello" : "world"} }
- $facet : SQL문에서 union all 과 비슷한 맥락
공식 문서 링크 : https://www.mongodb.com/docs/manual/reference/operator/aggregation/facet/ - $lookup : SQL문에서 join과 비슷한 맥락
→공식문서를 보면 다양한 사용법이 있기 때문에, 자세한 내용은 다른포스팅에 따로 정리해볼 예정 - $replaceRoot : 도큐먼트의 모양을 바꾸는 스테이지. 도큐먼트의 내용을 newRoot 파라미터에 설정한 값으로 대체할 수 있으며, 서브 도큐먼트를 도큐먼트 전체의 내용으로 바꾸려고 할 때 특히 더 유용하다.
- $sortByCount : 기존 $group + $sort 스테이지를 통해 표현했던 의미를 좀 더 간편하게 처리할 수 있는 스테이지.
// $sortByCount 방식 { $sortByCount : <expression> } // 기존 방식 { $group : {_id : <expression>, count : { $sum : 1 } } }, { $sort : { count : 1 } } 위의 두 방식은 동일한 결과를 출력 ↓ 실제 사용 예시 db.rating.aggregate([ { $sortByCount : "$rating" } ]) ↓ 결과 {"_id" : 5, "count" : 4} {"_id" : 3, "count" : 2} {"_id" : 4, "count" : 2} {"_id" : 2, "count" : 1} {"_id" : 1, "count" : 1}
-
$unset : 지정한 필드를 없애고 싶을 때 사용. 특정 조건을 만족하는 도큐먼트에만 적용할 수도 있고 모든 도큐먼트에 적용할 수도 있음
- $let : var라는 표현식을 사용하여 값을 담은 변수를 만들고 in을 사용하여 최종 return
aggregate 집계 쿼리를 구현 중에 ‘다른 컬렉션’에 들어있는 특정 필드의 모든 값을 일단 배열형태로 가져와야하는 경우가 있었다. 이때 사용할 수 있는 스테이지로는 $lookup, 그리고 $group 스테이지 + $push 연산자. 이 중 $group 스테이지를 사용할때 그룹핑할 기준이 담기는 _id 필드에 공백(““)만 설정하여 배열에 담고싶은 값이 담긴 필드를 $push로 지정하여 처리하였다.
ex)
{
"$group" : {
"_id" : "",
"testCreateField" : {
"$push" : "$usage_cost"
}
}
집계 파이프라인 연산자
-
문자열연산자
-
concat
-
strcasecmp
-
substr
-
substrCP
-
strLenCP
-
toLower
-
toUpper
-
- 산술연산자
- add
- divide
- mod
- multiply
- subtract
- 날짜, 시간 연산자
- toDate
- dayOfYear
- dayOfMonth
- dayOfWeek
- year
- month
- week
- hour
- minute
- second
- millisecond
- 논리연산자
- cond
- ifNull
- not
- or
- and
- nor
- 비교연산자
- cmp
- eq
- ne
- gt
- gte
- lt
- lte
- in
- nin
- 배열연산자
- setEquals
- setIsSubset
- setDifference
- setUnion
- arrayElemAt
- 쿼리속 집계파이프라인 연산자
- expr
Leave a comment