文档菜单
文档首页
/ / /
PHP 库手册
/

监控数据更改

本页内容

  • 概述
  • 示例数据
  • 打开更改流
  • 修改更改流输出
  • 修改watch()行为
  • 包含预图像和后图像
  • 更多信息
  • API 文档

在本指南中,您可以了解如何使用更改流来监控数据实时变更。更改流是MongoDB服务器功能,允许应用程序订阅集合、数据库或部署上的数据变更。

当使用MongoDB PHP库时,您可以调用watch()方法以返回MongoDB\ChangeStream实例。然后,您可以遍历MongoDB\ChangeStream实例以监控数据变更,例如更新、插入和删除。

本指南中的示例使用来自Atlas示例数据集sample_restaurants数据库中的restaurants集合。要从您的PHP应用程序访问此集合,实例化一个连接到Atlas集群的MongoDB\Client并将以下值分配给您的$collection变量

$collection = $client->sample_restaurants->restaurants;

提示

要了解如何创建免费的MongoDB Atlas集群并加载数据集,请参阅Atlas入门指南。

一些示例使用toJSON()函数将更改事件(BSON文档)表示为扩展JSON。要使用此函数,请将以下代码粘贴到您的应用程序文件中

function toJSON(object $document): string
{
return MongoDB\BSON\Document::fromPHP($document)->toRelaxedExtendedJSON();
}

要打开变更流,请调用 watch() 方法。调用 watch() 方法的实例决定了变更流监控的事件范围。您可以在以下类的实例上调用 watch() 方法

  • MongoDB\Client:监控 MongoDB 部署中的所有更改

  • MongoDB\Database:监控数据库中所有集合的更改

  • MongoDB\Collection:监控集合中的更改

以下示例在 restaurants 集合上打开变更流,并输出发生的更改

$changeStream = $collection->watch();
for ($changeStream->rewind(); true; $changeStream->next()) {
if ( ! $changeStream->valid()) {
continue;
}
$event = $changeStream->current();
echo toJSON($event), PHP_EOL;
if ($event['operationType'] === 'invalidate') {
break;
}
}

要开始监控更改,运行前面的代码。然后,在另一个壳中,修改 restaurants 集合。以下示例更新一个具有 'Blarney Castle' 字段值的文档

$result = $collection->updateOne(
['name' => 'Blarney Castle'],
['$set' => ['cuisine' => 'Irish']]
);

当您更新集合时,变更流应用程序会打印发生的更改。打印的更改事件类似于以下输出

{ "_id" : { "_data" : "..." }, "operationType" : "update", "clusterTime" :
{ "$timestamp" : { ... } }, "wallTime" : { "$date" : "..." }, "ns" : { "db" :
"sample_restaurants", "coll" : "restaurants" }, "documentKey" : { "_id" :
{ "$oid" : "..." } }, "updateDescription" : { "updatedFields" : { "cuisine" : "Irish" },
"removedFields" : [ ], "truncatedArrays" : [ ] } }

要修改变更流输出,您可以将数组中的管道阶段作为参数传递给 watch() 方法。您可以在数组中包含以下阶段

  • $addFields$set:向文档中添加新字段

  • $match:过滤文档

  • $project:投影文档的字段子集

  • $replaceWith$replaceRoot:将输入文档替换为指定的文档

  • $redact:限制文档的内容

  • $unset:从文档中删除字段

以下示例将包括$match阶段的管道传递给watch()方法。这指示watch()方法仅在更新操作发生时输出事件

$pipeline = [['$match' => ['operationType' => 'update']]];
$changeStream = $collection->watch($pipeline);
for ($changeStream->rewind(); true; $changeStream->next()) {
if ( ! $changeStream->valid()) {
continue;
}
$event = $changeStream->current();
echo toJSON($event), PHP_EOL;
if ($event['operationType'] === 'invalidate') {
break;
}
}

要修改watch()方法的行为,您可以将一个选项数组作为参数传递给watch()。以下表格描述了您可以在数组中设置的可用选项

选项
描述
fullDocument
指定是否在更改后显示完整的文档,而不是仅显示对文档所做的更改。有关此选项的更多信息,请参阅本指南中的包括预图像和后图像部分。
fullDocumentBeforeChange
指定是否显示更改前的完整文档,而不是仅显示对文档所做的更改。有关此选项的更多信息,请参阅包括预图像和后图像
startAfter
指示watch()在恢复令牌中指定的操作之后启动新的更改流。此字段允许在无效事件之后恢复通知。
每个更改流事件文档都包含一个作为_id字段的恢复令牌。传递表示您想要在之后恢复的操作的更改事件文档的整个_id字段。
此选项与resumeAfterstartAtOperationTime互斥。
startAtOperationTime
指示更改流仅提供在指定时间戳或之后发生的更改。
此选项与startAfterresumeAfter互斥。
collation
为更改流游标设置排序。

有关watch()选项的完整列表,请参阅API文档中的MongoDB\Collection::watch()

重要

只有当您的部署使用MongoDB v6.0或更高版本时,您才能在集合上启用前像和后像。

默认情况下,当您在集合上执行操作时,相应的更改事件仅包含该操作修改的字段的增量。要查看更改前或更改后的完整文档,请将fullDocumentBeforeChangefullDocument选项指定为watch()方法的一个数组参数。

前像是更改之前文档的完整版本。要包括前像在更改流事件中,将fullDocumentBeforeChange选项设置为以下值之一

  • MongoDB\Operation\Watch::FULL_DOCUMENT_BEFORE_CHANGE_WHEN_AVAILABLE:更改事件包含修改文档的前像。如果前像不可用,则此更改事件字段具有null值。

  • MongoDB\Operation\Watch::FULL_DOCUMENT_BEFORE_CHANGE_REQUIRED:更改事件包含修改文档的前像。如果前像不可用,则服务器引发错误。

后像是更改之后文档的完整版本。要包括后像在更改流事件中,将fullDocument选项设置为以下值之一

  • MongoDB\Operation\Watch::FULL_DOCUMENT_UPDATE_LOOKUP:更改事件包含更改后某个时间点的整个更改文档的副本。

  • MongoDB\Operation\Watch::FULL_DOCUMENT_WHEN_AVAILABLE:更改事件包含修改文档的后像。如果后像不可用,则此更改事件字段具有null值。

  • MongoDB\Operation\Watch::FULL_DOCUMENT_REQUIRED:更改事件包含修改文档的后像。如果后像不可用,则服务器引发错误。

以下示例在集合上调用watch()方法,并通过设置fullDocument选项包括更新文档的后像

$options = ['fullDocument' => MongoDB\Operation\Watch::FULL_DOCUMENT_UPDATE_LOOKUP];
$changeStream = $collection->watch([], $options);
for ($changeStream->rewind(); true; $changeStream->next()) {
if ( ! $changeStream->valid()) {
continue;
}
$event = $changeStream->current();
echo toJSON($event), PHP_EOL;
if ($event['operationType'] === 'invalidate') {
break;
}
}

当更改流应用程序在单独的shell中运行时,使用前面的更新示例通过在restaurants集合中更新文档,打印出类似以下输出的更改事件

{ "_id" : { "_data" : "..." }, "operationType" : "update", "clusterTime" :
{ "$timestamp" : { ... } }, "wallTime" : { "$date" : "..." },
"fullDocument" : { "_id" : { "$oid" : "..." }, "address" : { "building" :
"202-24", "coord" : [ -73.925044200000002093, 40.559546199999999772 ], "street"
: "Rockaway Point Boulevard", "zipcode" : "11697" }, "borough" : "Queens",
"cuisine" : "Irish", "grades" : [ ...], "name" : "Blarney Castle", "restaurant_id" :
"40366356" }, "ns" : { "db" : "sample_restaurants", "coll" : "restaurants" },
"documentKey" : { "_id" : { "$oid" : "..." } }, "updateDescription" :
{ "updatedFields" : { "cuisine" : "Irish" }, "removedFields" : [ ],
"truncatedArrays" : [ ] } }

提示

有关前像和后像的更多信息,请参阅MongoDB服务器手册中的带有文档前像和后像的更改流

要了解更多有关更改流的信息,请参阅MongoDB服务器手册中的更改流

要了解更多关于本指南中讨论的任何方法或类型,请参阅以下API文档

  • MongoDB\Client::watch()

  • MongoDB\Database::watch()

  • MongoDB\Collection::watch()

  • MongoDB\Collection::updateOne()

返回

不同字段值