Docs Menu
Docs Home
/ / /
PHP ライブラリ マニュアル
/

追尾可能 (tailable) カーソルの反復

項目一覧

  • Overview
  • 通常のカーソルの手動反復処理
  • 追尾可能 (tailable) カーソルの反復処理

ドライバーがクエリまたはコマンド(例: 集計 )、操作の結果は MongoDB\Driver\Cursor を介して返されます オブジェクト。カーソル クラスは PHP の イテレータ を実装します インターフェースにより、 で反復処理され、 イテラブルforeach を操作する任意の PHP 関数とのインターフェースが可能になります 。他のデータベース ドライバーの結果オブジェクトと同様に、MongoDB のカーソルはフォワード反復のみをサポートしているため、書き換えたり、 foreachで複数回使用したりすることはできません。

追尾可能 (tailable) カーソルは、クライアントが結果を読み取った後、使用可能なドキュメントを増やすまで待機できる MongoDB カーソルの特殊なタイプです。 これらのカーソルは、主にCapped コレクションChange Streamsで使用されます。

通常のカーソルはforeachを使用して 1 回反復できますが、そのアプローチは 追尾可能 (tailable) カーソルでは機能しません。 foreachを追尾可能 (tailable) カーソルと併用する場合、初期結果セットの末尾に到達するとループは停止します。 2 つ目のforeachを使用してカーソルの反復処理を続行しようとすると、PHP はカーソルを巻き戻すのを試みるため、例外がスローされます。 したがって、追尾可能 (tailable) カーソルから読み取るには、 イテレータ を直接使用する必要があります。 API。

注意

1.9.0拡張機能のバージョンext-mongodb より前では、カーソル クラスは イテレータ を実装していません インターフェースを使用します。以下の メソッドを使用してカーソルを手動で反復処理するには、まず イテレータ イテレータでラップする必要があります。

追尾可能 (tailable) カーソルが反復処理される方法を確認する前に、まず、 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()を呼び出すと、カーソル上のすべての結果が使い果たされたため、例外がスローされます。

foreachこの例の目的は、PHP の イテレータ を使用して、 と手動反復処理の機能同等性を示すことです。 API。通常のカーソルの場合、簡潔なforeachループではなく、結果を手動で反復処理する理由はほとんどありません。

追尾可能 (tailable) カーソルの動作を示すには、「プロデューサー」と「コンシューマー」の 2 つのスクリプトが必要です。 プロデューサー スクリプトは、 MongoDB\Database::createCollection()を使用して新しい Capped コレクションを作成し、1 秒ごとにそのコレクションに新しいドキュメントの挿入を続行します。

<?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) カーソルを使用して挿入されたドキュメントを読み取るためのコンシューマー スクリプトを実行します。 最初に、 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);
}

このコンシューマー スクリプトを実行すると、Cappedコレクション内のすべての結果をすぐに使い果たし、その後終了します。 カーソルを巻き戻すと、例外がスローされるため、2 つ目のforeachを追加することはできません。 これは、 イテレータ を使用して反復プロセスを直接制御するための適切なユースケースです インターフェースを使用します。

<?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 コレクション内のすべての結果をすばやく出力することで起動します。ただし、初期結果セットの末尾に到達しても終了しません。 追尾可能 (tailable) カーソルを使用しているため、 next()を呼び出すと、例外がスローされるのではなく、ブロックして追加の結果を待機します。 また、 valid()を使用して、各ステップで実際に読み取り可能なデータがあるかどうかを確認します。

TAILABLE_AWAITカーソルを使用するようにしたため、サーバーはドライバーへの応答を一定時間遅延させます。 この例では、MongoDB\Collection::find()maxAwaitTimeMSオプションを指定して、サーバーが約 100 ミリ秒ブロックすることをリクエストしています

戻る

Indexes