문서 메뉴

문서 홈PHP 라이브러리 매뉴얼

Tailable Cursor 반복

이 페이지의 내용

  • 개요
  • 일반 커서 수동 반복
  • 테일 커서(tailable cursor) 반복하기

드라이버가 쿼리 또는 명령(예: aggregate)을 실행하면 작업 결과가 MongoDB\Driver\Cursor 객체. Cursor 클래스는 PHP의 반복자를 구현합니다. 인터페이스를 사용하여 로 반복 하고 이터러블과 함께 작동하는 foreach 모든 PHP 함수와 인터페이스할 수 있습니다. . 다른 데이터베이스 드라이버의 결과 객체와 마찬가지로 MongoDB의 커서는 정방향 반복만 지원하므로 를 foreach 여러 번 되감거나 사용할 수 없습니다.

테일 커서(tailable cursor )는 클라이언트가 일부 결과를 읽은 다음 더 많은 문서를 사용할 수 있을 때까지 기다릴 수 있는 특수한 유형의 MongoDB 커서입니다. 이러한 커서는 주로 고정 사이즈 컬렉션변경 스트림에 사용됩니다.

일반 커서는 으로 한 번 반복할 수 foreach 있지만, 이 접근 방식은 테일 커서(tailable foreach cursor)에서는 작동하지 않습니다. 을 테일 커서(tailable cursor)와 함께 사용하면 초기 결과 집합의 끝에 도달하면 루프가 중지됩니다.foreach PHP가 커서를 되감으려고 시도하기 때문에 두 번째 을(를) 사용하여 커서를 계속 반복하려고 하면 예외가 발생합니다. 따라서 테일 커서(tailable cursor)에서 읽으려면 반복자 (iterator) 메서드를 직접 사용해야 합니다. API.

참고

버전 1 이전.9.0 확장자의 ext-mongodb 에서 커서 클래스가 반복자 를 구현하지 않습니다. 인터페이스. 아래 방법을 사용하여 커서를 수동으로 반복하려면 먼저 IteratorIterator로 래핑해야 합니다.

tailable cursor를 반복하는 방법을 살펴보기 전에 먼저 Iterator 메서드가 커서와 상호 작용하는 방식을 살펴보겠습니다.

다음 예에서는 레스토랑 5개를 찾고 foreach 을(를) 사용하여 결과를 확인합니다.

<?php
$collection = (new MongoDB\Client)->test->restaurants;
$cursor = $collection->find([], ['limit' => 5]);
foreach ($cursor as $document) {
var_dump($document);
}

이 예제는 매우 간결하지만 실제로는 꽤 많은 작업이 진행되고 있습니다.foreach 구문은 이터러블(이$cursor 경우 )을 되감는 것으로 시작됩니다. 그런 다음 현재 위치가 유효한지 확인합니다. 위치가 유효하지 않으면 루프가 종료됩니다. 그렇지 않으면 그에 따라 현재 키와 값에 액세스하고 루프 본문이 실행됩니다. 휴식 시간 가정 이 발생하지 않은 경우 반복자는 다음 위치로 이동하고 제어는 유효성 검사로 다시 이동한 다음 루프가 계속됩니다.

foreach 의 내부 작동을 통해 이제 앞의 예제를 반복자 메서드를 직접 사용하도록 변환할 수 있습니다.

<?php
$collection = (new MongoDB\Client)->test->restaurants;
$cursor = $collection->find([], ['limit' => 5]);
$cursor->rewind();
while ($cursor->valid()) {
$document = $cursor->current();
var_dump($document);
$cursor->next();
}

참고

while 루프가 자연스럽게 종료된 후 $cursor->next() 을(를) 호출하면 커서의 모든 결과가 소진되었으므로 예외가 발생합니다.

이 예제의 목적은 PHP의 Iterator 를 사용하여 와 수동 반복 간의 기능적 동등성을 설명하는 foreach 것입니다. API. 일반 커서의 경우 간결한 루프 대신 결과를 수동으로 반복할 이유가 거의 foreach 없습니다.

tailable cursor의 조치를 시연하려면 "프로듀서"와 "소비자"라는 두 개의 스크립트가 필요합니다. 프로듀서 스크립트는 MongoDB\Database::createCollection() 를 사용하여 새 고정 사이즈 컬렉션을 생성하고 매초마다 해당 컬렉션에 새 문서를 삽입합니다.

<?php
$database = (new MongoDB\Client)->test;
$database->createCollection('capped', [
'capped' => true,
'size' => 16777216,
]);
$collection = $database->selectCollection('capped');
while (true) {
$collection->insertOne(['createdAt' => new MongoDB\BSON\UTCDateTime()]);
sleep(1);
}

생산자 스크립트가 계속 실행 중인 상태에서 소비자 스크립트를 실행하여 MongoDB\Collection::find() cursorType 으로 표시된 tailable cursor를 사용하여 삽입된 문서를 읽습니다. 먼저 foreach 를 사용하여 단점을 설명합니다.

<?php
$collection = (new MongoDB\Client)->test->capped;
$cursor = $collection->find([], [
'cursorType' => MongoDB\Operation\Find::TAILABLE_AWAIT,
'maxAwaitTimeMS' => 100,
]);
foreach ($cursor as $document) {
printf("Consumed document created at: %s\n", $document->createdAt);
}

이 소비자 스크립트를 실행하면 고정 사이즈 컬렉션의 모든 결과가 빠르게 소진된 후 종료된다는 것을 알 수 있습니다. 두 번째 을 추가하면 foreach 커서를 되감려고 할 때 예외가 발생하므로 추가할 수 없습니다. 이는 Iterator 를 사용하여 반복 프로세스를 직접 제어하기 위한 잘 알려진 사용 사례입니다. 인터페이스.

<?php
$collection = (new MongoDB\Client)->test->capped;
$cursor = $collection->find([], [
'cursorType' => MongoDB\Operation\Find::TAILABLE_AWAIT,
'maxAwaitTimeMS' => 100,
]);
$cursor->rewind();
while (true) {
if ($cursor->valid()) {
$document = $cursor->current();
printf("Consumed document created at: %s\n", $document->createdAt);
}
$cursor->next();
}

foreach 예제와 마찬가지로, 소비자 스크립트의 이 버전은 capped collection의 모든 결과를 빠르게 인쇄하는 것으로 시작합니다. 그러나 초기 결과 집합의 끝에 도달해도 종료되지는 않습니다. 여기서는 tailable cursor로 작업하고 있으므로 next() 을(를) 호출하면 예외가 발생하지 않고 추가 결과가 차단되고 추가 결과가 기다립니다. 또한 valid() 를 사용하여 각 단계에서 실제로 읽을 수 있는 데이터가 있는지 확인합니다.

TAILABLE_AWAIT 커서를 사용하도록 선택했으므로 서버는 설정된 시간 동안 드라이버에 대한 응답을 지연합니다. 이 예제에서는 maxAwaitTimeMS 옵션을 MongoDB\Collection::find() 에 지정하여 서버가 약 100밀리초 동안 차단하도록 요청했습니다.

← 인덱스