IT/MongoDB

MongoDB -aggregate

KeepGooing 2019. 7. 10. 00:39
반응형

몽고디비를 사용하다 보면 Array 타입의 데이터를 다룰 일이 생깁니다.

문제는 Array 안에 또 다른 Array가 배열로 존재하고 있는 경우 조작하기가 까다로워지죠.

 

이런 경우의 어려움을 겪는 분이 혹시나 있을까 싶어

오늘은 유용하게 활용할 수 있는 aggregate 함수 예제를 소개 해드릴까 합니다.

 

 

조건 없이 find 함수를 활용하여 조회한 값 입니다.

위의 data를 aggregate를 활용하여 다양한 조건을 만족하는 값을 조회해보겠습니다.

 

 

1. 우선 NeccesaryParam의 값이 nec이고 year는 2019 그리고 month는 7인 값만 뽑아오겠습니다.

(테스트 용도이기에 데이터 타입을 String으로 맞췄지만 보통은 int롤 맞춰줍니다.)

 

db.getCollection('test').aggregate([

 {$match : { "NeccesaryParam": "nec", "year" : "2019", "month" : "7" } }, 

])

 

2. 이어서 array 안에 있는 속성 값 하나를 기준으로 내림차순(정렬)을 하기위해 array를 풀어줍니다($unwind 제한자 활용).

 

db.getCollection('test').aggregate([
  {$match : { "NeccesaryParam": "nec", "year" : "2019", "month" : "7" } },
  {$unwind: '$bookList'},
])

 

match에 이어 {$unwind: '$bookList'}, 를 적용한 값 

 

3. 위 같이 array로 묵였있던 값을 Object를 변환하여 $sort 제한자가 적용될 수 있도록 작업을 하고,

Object 안의 하나의 속성 값을 기준으로 내림(-1) 혹은 올림(1) 차순으로 정렬하면 됩니다.

 

db.getCollection('test').aggregate([
  {$match : { "NeccesaryParam":"nec","year":"2019","month":"7"}},
  {$unwind: '$bookList'},
  {$sort: { 'bookList.rank' : -1}},
])

 

 

이전에 $unwind를 하지 않으면 $sort 제한자는 적용되지 않습니다. 

 

 

4. 이후 group하기 전에 페이징 처리를 하고 싶다면 $group 전에 $skip과 $limit를 적용합니다. 

 

db.getCollection('test').aggregate([
  {$match : { "NeccesaryParam":"nec","year":"2019","month":"7"}},
  {$unwind: '$bookList'},
  {$sort: { 'bookList.rank' : 1}},
  {$skip:2},
  {$limit:3},
])

 

skip에2를 적용하여 랭킹 1, 2를 제외한 3부터 나오는 것을 확인할 수 있는 이미지(배열은 0부터 시작임을 잊지말자)

 

5. 마지막으로 작업을 맞추고 본래의 array로 재그룹화를 한다. 이때 $group 안에 $push라는 제한자를 쓰는 것에 주목하자

 

db.getCollection('test').aggregate([
  {$match : { "NeccesaryParam":"nec","year":"2019","month":"7"}},
  {$unwind: '$bookList'},
  {$sort: { 'bookList.rank' : 1}},
  {$skip:2},
  {$limit:3},
  {$group: {'_id': '$_id', bookList : {$push : '$bookList'}}}
]);

 

$group과 $push를 활용하여 위의 조건을 만족하는 본래의 형태로 돌아간 모습

여기서 $push 배열의 필드의 값으로 투사합니다.

 

 

aggregate 안의 여러 json 형태로 들어간다는면 반드시 [] (중괄호를)넣어야 합니다.

 

이외도 다양한 제한자를 활용하여 논리적으로 원하는 값을 추출혹은 집계 조회할 수 있습니다.

 

물론 저장도 가능합니다.

 

핵심 포인트로

1.  json형태를 고려하여 제한자를 사용할 것과

2. 제한자의 순서를 고려하여 쿼리를 짜야한다는 것입니다. (가령 array 안의 속성 값을 기준으로 정렬을 하고 싶다면

일단 $unwind를 활용하여 object를 전환하여 $sort를 진행하는 경우를 예로 들 수 있습니다.)

 

 

 

관련하여 조금 응용하여 위의 값을 활용한 쿼리를 공유하오니

참고하셔서 각자의 콜렉션의 db를 조회하는 데 유용하게 사용하시길 바랍니다.



db.test.aggregate([
    {$match : { "neccessaryCode":"M","year":"2019","month":"7"}},
    {$unwind: '$bookList'},
    {$group: {'_id': '$_id', bookList : {$push : '$bookList'}}},
    {$project: {"bookList":1, bookListCount: {$size: '$bookList'}}},
    {$unwind: '$bookList'},
    {$sort: {'bookList.loanCnt' :-1, 'bookList.rank' : 1}},
    {'$skip': 0 },
    {'$limit': 5 },
    {$group: {'_id': '$_id' ,bookList : {$push : '$bookList'}, count :{$first : '$bookListCount'}}}

 

매치하고 풀어서 bookList로 array 값 푸시한 그룹

그다음 bookList 사이즈 값 구하고(size는 array로 묶인 것만 object는 카운트 안됨) 
이어서 다시 풀어서 정렬하고 정렬한 값에서 skip과 limit를 구하여 이전에 구한 값과 다시 재 그룹화 하여 최종 값을 구하는 과정이다.



/* $project의 경우는 추출이며 이 경우에는 bookList의 값 하나를 활용하여 bookListCount 값을 $size 제한자를 활용하여 구하는 것입니다. */

 

감사합니다.

반응형

'IT > MongoDB' 카테고리의 다른 글

MONGODB - find  (0) 2020.06.13
MONGODB - 기본구조  (0) 2020.06.09
몽고DB 집계 함수  (0) 2019.07.30
클라우드/빅데이터  (0) 2019.07.27
MongoDB CRUD Operations(핵심)  (0) 2019.07.07