21. MongoDB Query Part 11. - $snap
이전 포스팅에서 약속하였듯이 이번 글에서는 $snapshot
쿼리 옵션에 대해서 자세히 알아보도록 하겠습니다.
일반적인 데이터 처리 절차는 다음과 같습니다:
MongoDB로부터 도큐먼트를 불러오고, 이에 대한 처리를 한 후, 처리에 대한 결과를 다시 저장합니다.
예를 들어 다음 코드를 살펴보도록 하겠습니다.
cursor = db.myCollection.find();
while (cursor.hasNext())
{
var doc = cursor.next();
doc = process(doc);
db.myCollection.save(doc);
}
위의 코드 내용을 살펴보면,
- 변수
cursor
에myCollection
으로부터 검색된 도큐먼트를 저장하였으며, cursor
에 저장된 내용을 변수doc
으로 얻은 후,doc
에 대한 처리를 한 후, 처리 결과를 다시 변수doc
으로 저장하고,doc
을myCollection
에 저장(save)하였습니다.- 그리고
cursor
는 다음 도큐먼트로 이동하여 더이상 도큐먼트가 없을 때까지 이를 반복합니다.
만약 처리된 도큐먼트의 사이즈가 처리되기 전보다 크면 어떤 일이 벌어질까요? 그림을 통해 이에 대한 설명을 하도록 하겠습니다.
이해를 돕기 위해 다음 그림을 살펴보도록 하겠습니다.
[그림 1]에서 각 도형을 각각 도큐먼트로 생각하겠습니다. find
명령이 실행될 때 결과는 컬렉션의 시작(가장 왼쪽 도큐먼트)부터 가져오게 되며 하나씩 처리할 때 cursor
는 오른쪽으로 이동하게 됩니다.
만약 [그림 2]와 같이 두번째 도큐먼트(녹색 둥근사각형)를 처리한 결과 원래의 사이즈보다 커지면,
처리된 후의 두번째 도큐먼트는 원래의 위치였던 첫번째와 세번째 도큐먼트 사이에 저장 가능한 충분한 크기가 확보되지 않았으므로 새로운 위치로 이동하여야 합니다.
일반적으로 가장 마지막(맨 오른쪽)으로 위치를 옮깁니다.
이 후, cursor
는 다음 도큐먼트로 이동하여 처리를 계속 진행하게 되는데, 이와 같은 식으로 진행하게 되면 [그림 4]와 같이 이미 처리된 도큐먼트를 마지막에 다시 만나게 됩니다.
이를 해결하고자 하는 것이 바로 snapshot
쿼리 옵션입니다.
$snapshot
쿼리 옵션이 추가되면 쿼리는 도큐먼트 배치를 도큐먼트의 원래 위치로 인식하고 처리하게 됩니다.
쿼리 용법은 다음과 같이 세가지 중 하나를 선택하여 사용할 수 있습니다:
db.myCollection.find().snapshot()
db.myCollection.find()._addSpecial( "$snapshot", true )
db.myCollection.find( { $query: {}, $snapshot: true } )
- 주의사항
- sharded collection과
$snapshot
을 함께 사용해서는 안 됩니다. $hint
혹은$orderby
와 함께 사용해서도 안 됩니다.
- sharded collection과