监控数据更改
概述
在本指南中,您可以了解如何使用更改流来监控数据实时变更。更改流是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()
方法的行为,您可以将一个选项数组作为参数传递给watch()
。以下表格描述了您可以在数组中设置的可用选项
选项 | 描述 |
---|---|
fullDocument | 指定是否在更改后显示完整的文档,而不是仅显示对文档所做的更改。有关此选项的更多信息,请参阅本指南中的包括预图像和后图像部分。 |
fullDocumentBeforeChange | 指定是否显示更改前的完整文档,而不是仅显示对文档所做的更改。有关此选项的更多信息,请参阅包括预图像和后图像。 |
startAfter | 指示 watch() 在恢复令牌中指定的操作之后启动新的更改流。此字段允许在无效事件之后恢复通知。每个更改流事件文档都包含一个作为 _id 字段的恢复令牌。传递表示您想要在之后恢复的操作的更改事件文档的整个_id 字段。此选项与 resumeAfter 和startAtOperationTime 互斥。 |
startAtOperationTime | 指示更改流仅提供在指定时间戳或之后发生的更改。 此选项与 startAfter 和resumeAfter 互斥。 |
collation | 为更改流游标设置排序。 |
有关watch()
选项的完整列表,请参阅API文档中的MongoDB\Collection::watch()。
包括前像和后像
重要
只有当您的部署使用MongoDB v6.0或更高版本时,您才能在集合上启用前像和后像。
默认情况下,当您在集合上执行操作时,相应的更改事件仅包含该操作修改的字段的增量。要查看更改前或更改后的完整文档,请将fullDocumentBeforeChange
或fullDocument
选项指定为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 文档
要了解更多关于本指南中讨论的任何方法或类型,请参阅以下API文档