MongoDB에서 순서를 유지한 채 최근 문서 10개 가져오기
MongoDB에서 컬렉션에 저장된 문서 중 가장 최근에 삽입된 10개를 조회하되, 기존의 저장 순서는 그대로 유지하고 싶은 경우가 있습니다. 이럴 때는 skip() 메서드를 활용하면 간단하게 해결할 수 있습니다.
핵심 아이디어는 다음과 같습니다. 컬렉션의 전체 문서 개수에서 10을 뺀 값, 즉 count() - 10을 skip()에 지정하면 앞부분의 오래된 문서들은 건너뛰고 마지막 10개의 문서만 원래 순서대로 반환됩니다.
1. 샘플 컬렉션 생성하기
먼저 실습을 위해 컬렉션을 만들고 여러 개의 문서를 삽입해 보겠습니다.
> db.demo500.insertOne({value:10});{ "acknowledged" : true, "insertedId" : ObjectId("5e8749c5987b6e0e9d18f55a")}> db.demo500.insertOne({value:1200});{ "acknowledged" : true, "insertedId" : ObjectId("5e8749c8987b6e0e9d18f55b")}> db.demo500.insertOne({value:19});{ "acknowledged" : true, "insertedId" : ObjectId("5e8749cb987b6e0e9d18f55c")}> db.demo500.insertOne({value:28});{ "acknowledged" : true, "insertedId" : ObjectId("5e8749cf987b6e0e9d18f55d")}> db.demo500.insertOne({value:50});{ "acknowledged" : true, "insertedId" : ObjectId("5e8749d1987b6e0e9d18f55e")}> db.demo500.insertOne({value:70});{ "acknowledged" : true, "insertedId" : ObjectId("5e8749d4987b6e0e9d18f55f")}> db.demo500.insertOne({value:100});{ "acknowledged" : true, "insertedId" : ObjectId("5e8749d7987b6e0e9d18f560")}> db.demo500.insertOne({value:10});{ "acknowledged" : true, "insertedId" : ObjectId("5e8749d9987b6e0e9d18f561")}> db.demo500.insertOne({value:98});{ "acknowledged" : true, "insertedId" : ObjectId("5e8749dc987b6e0e9d18f562")}> db.demo500.insertOne({value:80});{ "acknowledged" : true, "insertedId" : ObjectId("5e8749e0987b6e0e9d18f563")}> db.demo500.insertOne({value:75});{ "acknowledged" : true, "insertedId" : ObjectId("5e874c73987b6e0e9d18f564")}> db.demo500.insertOne({value:68});{ "acknowledged" : true, "insertedId" : ObjectId("5e874c78987b6e0e9d18f565")}이렇게 하면 총 12개의 문서가 demo500 컬렉션에 저장됩니다.
2. 전체 문서 확인하기
find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 조회할 수 있습니다.
> db.demo500.find();
위 쿼리를 실행하면 다음과 같은 결과가 출력됩니다.
{ "_id" : ObjectId("5e8749c5987b6e0e9d18f55a"), "value" : 10 }{ "_id" : ObjectId("5e8749c8987b6e0e9d18f55b"), "value" : 1200 }{ "_id" : ObjectId("5e8749cb987b6e0e9d18f55c"), "value" : 19 }{ "_id" : ObjectId("5e8749cf987b6e0e9d18f55d"), "value" : 28 }{ "_id" : ObjectId("5e8749d1987b6e0e9d18f55e"), "value" : 50 }{ "_id" : ObjectId("5e8749d4987b6e0e9d18f55f"), "value" : 70 }{ "_id" : ObjectId("5e8749d7987b6e0e9d18f560"), "value" : 100 }{ "_id" : ObjectId("5e8749d9987b6e0e9d18f561"), "value" : 10 }{ "_id" : ObjectId("5e8749dc987b6e0e9d18f562"), "value" : 98 }{ "_id" : ObjectId("5e8749e0987b6e0e9d18f563"), "value" : 80 }{ "_id" : ObjectId("5e874c73987b6e0e9d18f564"), "value" : 75 }{ "_id" : ObjectId("5e874c78987b6e0e9d18f565"), "value" : 68 }3. skip()으로 최근 문서 10개 선택하기
정렬 순서를 변경하지 않으면서 가장 최근에 삽입된 문서 10개만 선택하는 쿼리는 다음과 같습니다.
> db.demo500.find().skip(db.demo500.count() - 10);
실행 결과는 아래와 같습니다.
{ "_id" : ObjectId("5e8749cb987b6e0e9d18f55c"), "value" : 19 }{ "_id" : ObjectId("5e8749cf987b6e0e9d18f55d"), "value" : 28 }{ "_id" : ObjectId("5e8749d1987b6e0e9d18f55e"), "value" : 50 }{ "_id" : ObjectId("5e8749d4987b6e0e9d18f55f"), "value" : 70 }{ "_id" : ObjectId("5e8749d7987b6e0e9d18f560"), "value" : 100 }{ "_id" : ObjectId("5e8749d9987b6e0e9d18f561"), "value" : 10 }{ "_id" : ObjectId("5e8749dc987b6e0e9d18f562"), "value" : 98 }{ "_id" : ObjectId("5e8749e0987b6e0e9d18f563"), "value" : 80 }{ "_id" : ObjectId("5e874c73987b6e0e9d18f564"), "value" : 75 }{ "_id" : ObjectId("5e874c78987b6e0e9d18f565"), "value" : 68 }동작 원리와 참고 사항
컬렉션에는 총 12개의 문서가 있으므로 count() - 10은 2가 됩니다. 따라서 skip(2)가 적용되어 처음 두 개의 문서(value가 10과 1200인 문서)는 건너뛰어지고, 나머지 10개의 문서가 원래 저장된 순서 그대로 반환됩니다.
다만 몇 가지 주의할 점이 있습니다.
- 성능:
skip()에 큰 값이 지정되면 해당 위치까지의 문서를 모두 훑어야 하므로, 대량의 데이터를 다루는 컬렉션에서는 성능 저하가 발생할 수 있습니다. - 버전 호환성: 최신 MongoDB 버전에서는
count()대신countDocuments()사용이 권장됩니다. 즉,db.demo500.find().skip(db.demo500.countDocuments() - 10)형태로 작성하는 것이 좋습니다. - 동시성: 쿼리 실행 중에 새로운 문서가 삽입되면 개수가 달라져 결과가 예상과 다를 수 있으므로, 데이터가 자주 변경되는 환경이라면 타임스탬프 필드 기반의 정렬 조회를 함께 고려하는 것이 안전합니다.