MongoDB 조회에 Aggregations pipeline을 이용하면 단계별 쿼리 적용으로 다양한 조회 결과를 뽑아 낼 수 있다.
Sample Data를 이용해서 대시보드를 만들어보자. (https://github.com/neelabalan/mongodb-sample-dataset/blob/main/sample_supplies/sales.json)
(예시 데이터)
{
"_id": {
"$oid": "5bd761dcae323e45a93ccfe8"
},
"saleDate": {
"$date": {
"$numberLong": "1427144809506"
}
},
"items": [
{
"name": "notepad",
"tags": [
"office",
"writing",
"school"
],
"price": {
"$numberDecimal": "35.29"
},
"quantity": {
"$numberInt": "2"
}
},
{
"name": "pens",
"tags": [
"writing",
"office",
"school",
"stationary"
],
"price": {
"$numberDecimal": "56.12"
},
"quantity": {
"$numberInt": "5"
}
},
{
"name": "envelopes",
"tags": [
"stationary",
"office",
"general"
],
"price": {
"$numberDecimal": "19.95"
},
"quantity": {
"$numberInt": "8"
}
},
{
"name": "binder",
"tags": [
"school",
"general",
"organization"
],
"price": {
"$numberDecimal": "14.16"
},
"quantity": {
"$numberInt": "3"
}
}
],
"storeLocation": "Denver",
"customer": {
"gender": "M",
"age": {
"$numberInt": "42"
},
"email": "cauho@witwuta.sv",
"satisfaction": {
"$numberInt": "4"
}
},
"couponUsed": true,
"purchaseMethod": "Online"
}
최종 데이터
→ saleData 내 items의 name을 기준으로 전체 수량을 구하고 수량이 많은 Top5개의 지점 조회하기 그리고 지점 내 갯수는 내림차순 정리로 정렬
{
"_id": "binder",
"totalQuantity": 100,
"topFiveRegionsByQuantity": {
"Seattle": 41,
"Denver": 26,
"New York": 14,
"Austin": 10,
"London": 9
}
}
일단 냄새가 나는 것은
기존 objectId값이 아닌 items name을 objectId값으로 가져와야 한다. 즉 기준이 되어야 하므로 $group, 그리고 총 수량을 조회하므로 $sum 또 내림차순 정리이므로 $sort를 활용해야 할 것 같다.
1) 내가 원하는 saleDate로 criteria 적용 ($match)
$gte → 이상, $lt : 미만
$match: {
saleDate: {
$gte: ISODate('2017-12-25T05:00:00.000Z'),
$lt: ISODate('2017-12-30T05:00:00.000Z')
}
}
2) items list값을 각각 펼쳐 나열하기 ($unwind)
items 리스트 내부 값을 가지고 group를 적용해야 하므로 items list 각각의 데이터를 1depth로 빼내야 한다.
$unwind : {
path: "$items",
}
빼내기 전
빼낸 후
$unwind를 사용하기 전에는 storeLocation : "Seattle" 하나의 Document에서 items를 리스트값으로 가지고 있었으나 items의 내부 리스트 값을 하나하나 flatmap 형태처럼 펼쳐 결과값이 나오는 것을 확인 할 수 있다.
3) item명과 region 기준($group)으로 조회하고 수량 더하기($sum)
$group : {
_id: {
item : '$items.name',
region: '$storeLocation',
},
quantity : {
$sum : '$items.quantity'
}
}
4) _id 필드 내 quantity 추가 ($addFields)
$addFields : {
'_id.quantity': '$quantity'
}
5) _id 필드 외 quantity 필드 삭제
$unset : {
'quantity'
}
6) _id 기준으로 임베디드 형태로 바꾸기 즉 특정 field값을 1depth Root로 빼내기 ($replaceRoot)
$replaceRoot : {
newRoot : '$_id'
}
7) item을 objectId로 지정하고($group) quantity를 모두 합산하기($sum) 그리고 Top5의 지점 조회 및 수량 정렬 ($topN, sort)
$group : {
_id: '$item',
totalQuantity: {
$sum: '$quantity'
},
topFiveRegionsByQuantity: {
$topN: {
output: {
k: '$region',
v: '$quantity'
},
sortBy: {
quantity: -1
},
n: 5
}
}
}
}
7-1) item을 objectId로 지정하고($group) quantity를 모두 합산
7-2) Top5의 지점 조회 및 수량 정렬 ($topN, sort), 단 topN은 5.2 버전부터 지원
8) 전체 수량(totalQuantity)
으로 내림차순 정렬(-1)
$sort : {
'totalQuantity': -1
}
}
9) 5개 지점(limit 5)까지만 조회하기
$limit : {
5
}
10) topFiveRegionsByQuantity 리스트를 json Object로 변경하기 ( $arrayToObject)
$set: {
topFiveRegionsByQuantity: {
$arrayToObject: '$topFiveRegionsByQuantity'
}
}
추가적인 Aggregate 메서드 값들은 해당 페이지에서 확인 할 수 있다.
https://www.mongodb.com/docs/manual/reference/method/js-collection/
'개발 지식 > Etc' 카테고리의 다른 글
[Intellij] 내가 사용하는 인텔리제이 단축키 (MAC) (0) | 2021.12.12 |
---|
댓글