본문 바로가기
개발 지식/Etc

[MongoDB] Building a Real-Time, Dynamic (Aggregate pipeline)

by 에르주 2023. 12. 18.
반응형

 

MongoDB 조회에 Aggregations pipeline을 이용하면 단계별 쿼리 적용으로 다양한 조회 결과를 뽑아 낼 수 있다.

https://www.mongodb.com/developer/products/atlas/building-real-time-dynamic-seller-dashboard/?utm_source=Iterable&utm_medium=email&utm_campaign=campaign_7536282

 

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'
}

 

replaceRoot

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를 모두 합산

group

7-2) Top5의 지점 조회 및 수량 정렬 ($topN, sort), 단 topN은 5.2 버전부터 지원

top

 

 

8) 전체 수량(totalQuantity) 으로 내림차순 정렬(-1)

$sort : {
  'totalQuantity': -1
 }
}

 

sort

9) 5개 지점(limit 5)까지만 조회하기

$limit : {
 5
}

 

limit

10) topFiveRegionsByQuantity 리스트를 json Object로 변경하기 ( $arrayToObject)

$set: {
  topFiveRegionsByQuantity: {
   $arrayToObject: '$topFiveRegionsByQuantity'
  }
 }

arrayToObject


추가적인 Aggregate 메서드 값들은 해당 페이지에서 확인 할 수 있다.

 

https://www.mongodb.com/docs/manual/reference/method/js-collection/

반응형

'개발 지식 > Etc' 카테고리의 다른 글

[Intellij] 내가 사용하는 인텔리제이 단축키 (MAC)  (0) 2021.12.12

댓글