웹 개발에서 게시판을 만들면 일반적으로 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

Admob을 포함한 광고 플랫폼은 개발자에게 용돈을 주는 고마운(?) 존재이다. 


물론 앱에 광고를 너무 많이 넣진 않고 미관을 해치지 않는 선에서만 추가한다.


처음부터 Admob을 추가해 앱을 개발하는 것을 고려했기 때문에 개발 초기에는 앱 실행 시 속도 차이를 크게 못느꼈다.


그러나 업데이트를 하면서 이런저런 기능을 추가하게 되면서 Admob이 실행 속도에 영향을 주기 시작했다.


참고로 앱의 실행 방식은 3가지가 존재한다.

Cold start, Hot start, Warm start


자세한 정보는 아래 링크에 자세히 서술되어 있다.

https://developer.android.com/topic/performance/vitals/launch-time


여기서 실행 속도가 느리다는 것은 Cold start이다.


Cold start 속도가 3초 후반대에서 4초 대로 늘면서 원인을 찾아본 결과 Admob이었다.


이러한 문제를 해결하기 위해서 검색한 결과


1. https://stackoverflow.com/a/31636336


위 링크에서 제공하는 다양한 방법이 있다.


2. https://stackoverflow.com/a/19446364


위 링크는 1번 링크의 첫번째 링크의 내용이다.


Handler를 사용하여 광고를 불러오는 소스 코드를 1초 딜레이를 주고 실행한다.


정말 단순히 Handler를 추가했을 뿐인데 2초에서 3초 사이로 실행 시간을 줄일 수 있었다.


by JamesY 2018. 7. 27. 23:52
| 1 2 3 4 5 ··· 8 |