웹 개발에서 게시판을 만들면 일반적으로 Pagination도  구현해 문서를 일정 단위 개수로 페이지를 보여줘야 한다.


전체 글 수를 간단하게 10개씩 보여주는 건 간단하게 가능하다. 하지만 전체 글이 90개라면 페이지는 1 ~ 10이 아닌


1 ~ 9까지만 보여줘야 한다. 이러한 작업을 위해서는 데이터베이스의 10개 단위 글만 가져오는 것이 아니라 전체 글 수도 가져와야


페이지 끝을 정해 줄 수 있다. 보통은 리스트를 가져오는 쿼리와 전체 글 수를 가져오는 쿼리를 각각 돌려 작업한다.


이러한 방법이 아닌 한번에 가능한 방법을 찾다가 Aggregation 파이프라인 명령어 중 하나인 $facet를 알게 되었다.


https://docs.mongodb.com/manual/reference/operator/aggregation/facet/


간단하게 설명하면 $facet는 하나의 스테이지 안에서 여러 개의 파이프라인을 돌릴 수 있도록 해주는 파이프라인이다.


{ $facet:
   {
      <outputField1>: [ <stage1>, <stage2>, ... ],
      <outputField2>: [ <stage1>, <stage2>, ... ],
      ...

   }
}


작성법은 다음과 같다.


하나의 결과값을 나타내는 outputField는 반드시 대괄호로 묶어야 하며 중괄호나 소괄호 사용 시 오류가 발생한다.


이 파이프라인을 이용해서 전체 글 수와 글 10개를 가져올 수 있다.


{ $facet: {     'documents': [ {$skip: 10}, {$limit: 10} ],     'total': [ { $count: 'count' } ] } }


documents 필드는 전체 글 중 11번째 글부터 20번째 글을 가져온다.

total 필드는 전체 글 수를 가지는 count 필드를 가진다.


Compass를 통해 Aggregation을 실행하면 결과값은 다음과 같다.


  1. documents
    :
    Array
    1. 0
      :
      Object
    2. 1
      :
      Object
    3. 2
      :
      Object
    4. 3
      :
      Object
    5. 4
      :
      Object
    6. 5
      :
      Object
    7. 6
      :
      Object
    8. 7
      :
      Object
    9. 8
      :
      Object
    10. 9
      :
      Object
  2. total
    :
    Array
    1. 0
      :
      Object
      1. count
        :
        34188


document 필드 내 각 object는 하나의 글 데이터이다.


이렇게 두번의 쿼리를 사용하지 않고 한번에 전체 글 수와 일정 개수의 문서를 가져올 수 있다.


단순히 게시판 뿐만 아니라 여러 결과 값을 하나의 데이터로 만들고 싶을 때 $facet를 사용하면 된다.

'MongoDB' 카테고리의 다른 글

사용자 정의 날짜/시간 포맷을 ISOdate로 변환  (0) 2018.08.19
by JamesY 2018. 9. 10. 17:41

API로 데이터를 받았는데 timestamp나 일반적인 날짜/시간 포맷이 아닌 경우가 있다.


whois에서 제공하는 도메인 조회 api의 경우 날짜 포맷이 YYYY. mm. dd. 형태로 되어있다.


나중에 날짜/시간을 읽어 분석하는 서비스를 제공해야할 경우 Mongo DB가 아래와 같이 읽을 수 없어 곤란한 상황이 올 수 있다.




이러한 경우 Aggregate의 $dateFromString을 사용하여 사용자 포맷을 정해주면 읽어들일 수 있다.


https://docs.mongodb.com/manual/reference/operator/aggregation/dateFromString/


{ $dateFromString: {
     dateString: <dateStringExpression>,
     format: <formatStringExpression>,
     timezone: <tzExpression>,
     onError: <onErrorExpression>,
     onNull: <onNullExpression>
} }


dateString : 변환할 날짜/시간 데이터 (필수)

format : 변환할 날짜/시간 포맷 (옵션)

timezone : 날짜/시간에 적용할 시간대 (옵션)

onError/onNull : 이벤트 발생 시 출력할 결과 (옵션)


여기서 예제는 앞서 말한 whois open api의 날짜 포맷인 YYYY. mm. dd. 로 한다.


db.dates.aggregate( [ { $project: { date: { $dateFromString: { dateString: '$date', format: '%Y. %m. %d.' } } } } ] )


$date는 날짜/시간 데이터를 가지고 있는 column명이다.

format은 api에서 제공하는 날짜/시간의 포맷을 넣었다.



위의 명령어를 mongo console에 적고 누르면 다음과 같이 결과가 출력된다.


성공적으로 변환되어 출력된 것을 볼 수 있다.


이제 위 명령어에 명령어를 덧붙여 collection에 적용되도록 한다.


적용을 하기 위해서는 $out을 사용한다.


https://docs.mongodb.com/master/reference/operator/aggregation/out/


*** $out의 collection은 위 명령어와 같은 collection을 쓸 경우 date를 제외한 모든 데이터 날라가므로 새로운 collection에 저장하도록 합시다. (테스트한다고 직접 겪어봄. 다 날림)


db.dates.aggregate( [ { $project: { date: { $dateFromString: { dateString: '$date', format: '%Y. %m. %d.' } } },

$out: { 'outputCollection' }

} ] )


이후 outputCollection을 확인해보면 console에서 확인한 결과값이 저장되어 있으므로 이후 update를 통해 데이터를 갱신하도록 한다.

by JamesY 2018. 8. 19. 01:40
| 1 |