티스토리 뷰
Offset-based paging
기본적으로 사용하게 되는 pagination 방식이다. API를 호출할 때 page, limit parameters를 사용하여 데이터를 호출한다.
// 한 페이지당 10개의 item을 보여주는 경우
const itemCount = 10;
db.items.find({ }).sort({_id:-1}).skip((page-1)* itemCount).limit(itemCount)
# API 요청 예시
curl https://api.github.com/user/repos?page=2&per_page=10
결과 list가 추가되거나 삭제되면 item이 빠지거나 2번 반복되는 경우가 생길 수 있다. 첫 번째 페이지에 10개를 요청하고 하나의 item이 지워졌다면 지워지기 전 11번째 있던 item이 10번째로 이동하게 된다. 따라서 두 번째 페이지를 요청할 때 11번째 있던 item이 누락된다.
Time-based paging
최신순으로 정렬된 결과를 반환하고 반환된 결과 중 마지막 item의 timestamp를 다음 페이지를 요청 시 사용한다.
// 한 페이지당 10개의 item을 보여주는 경우
const itemCount = 10;
let created // client에서 받은 timestamp
db.items.find({createdAt: {$lt: created }}).sort({_id:-1}).limit(itemCount)
curl https://example.com?created=1597273975343
Offset-based paging에서 발생하던 누락현상은 없어진다. 하지만 timestamp가 같은 item이 있을 경우 누락이 발생할 수 있다. 두 번째 페이지 요청 시 timestamp가 1597273975343였고 1597273975343에 생성된 item이 한개 이상이라면 두 번째 페이지 요청 시 1597273975343의 timestamp를 가지고 있는 item은 누락된다.
Cursor-based paging
Cursor-based paging은 반환된 결과의 마지막 item을 기준으로 다음 요청을 하는 것이다.
cursor를 선택할 때는 Unique, Orderable, Immutable한 field를 선택해야 한다. Time-based paging도 Cursor-based paging이지만 unique하지 않았다.
mongodb를 사용하는 경우 _id를 사용하여 Cursor-based paging을 구현할 수 있다.
const itemCount = 10;
const items = db.items.find({
_id: { $lt: req.query.next }
}).sort({
_id: -1
}).limit(10);
const next = items[items.length - 1]._id
생성순 정렬이 아닌 경우
_id는 Document가 새로 생성될 때 생성되어 생성 순으로 정렬되는 경우에 사용할 수 있지만 업데이트 순으로 정렬하거나 다른 기준으로 정렬되는 경우 _id를 사용할 수 없다.
_id외의 다른 field로 sorting하는 경우 아래의 코드에서와 같이 sort와 find에 모두 추가하여 query를 구성해야 한다.
const [nextUpdated, nextId] = req.query.next.split(‘_’);
const items = db.items.find({
$or: [{
updatedAt: { $lt: nextUpdated }
}, {
updatedAt: nextUpdated,
_id: { $lt: nextId }
}]
}).sort({
updatedAt: -1,
_id: -1,
}).limit(10);
const lastItem = items[items.length - 1];
const next = `${lastItem.updatedAt}_${lastItem._id}`;
updatedAt이 동일한 값이 있는 경우 _id로 구분할 수 있도록 구성한다.
Reference
'develop' 카테고리의 다른 글
VPC 내부 Neptune DB 클러스터 접근을 위한 리버스 프록시 서버 구성 (0) | 2020.09.18 |
---|---|
AWS WAFv2(terraform 작성 예시) (0) | 2020.08.27 |
iframe domain별 제한하기(Content Security Policy) (0) | 2020.08.06 |
commit message 관리 - conventional commit (0) | 2020.07.20 |
AWS ElasticSearch Service 운영 및 장애발생 해결 (0) | 2020.07.09 |
- Total
- Today
- Yesterday
- conventional commit
- Airflow
- Terraform
- Cognito
- aws
- AWS community day seoul
- JavaScript
- Python
- slowquery
- shorten
- nginx
- typescript
- NLP
- Cloudfront
- mongoDB
- sementic version
- graphql
- commit message
- lambda@edge
- Prisma
- inversify
- Lifecycle
- Elasticsearch
- Github Actions
- pagination
- mognodb
- nltk
- Clickjacking
- Neptune
- Develop
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |