Docs 菜单

Docs 主页开发应用程序MongoDB Manual

$changeStreamSplitLargeEvent(聚合)

在此页面上

  • 定义
  • 行为
  • 例子
$changeStreamSplitLargeEvent

MongoDB 7.0(和 6.0.9)新增内容。

如果变更流包含超过16 MB 的大型事件,则会返回BSONObjectTooLarge异常。从 MongoDB 7开始。 0 (以及6 . 0 . 9 ),可以使用$changeStreamSplitLargeEvent阶段将事件分割成更小的片段。

您应该仅在绝对必要时使用$changeStreamSplitLargeEvent 。例如,如果您的应用程序需要完整的文档前图像或后图像,并生成超过16 MB 的大型事件,请使用$changeStreamSplitLargeEvent

在决定使用$changeStreamSplitLargeEvent之前,应首先尝试减小变更事件的大小。例如:

  • 除非应用程序需要,否则不要请求文档前像或后像。这在更多情况下会生成fullDocumentfullDocumentBeforeChange字段,这些字段通常是变更事件中最大的对象。

  • 使用$project阶段仅包含应用程序所需的字段。这样可以减少变更事件的大小,并避免花费额外的时间将大型事件拆分为片段。这样可以在每个批次中返回更多变更事件。

管道中只能有一个$changeStreamSplitLargeEvent阶段,而且必须是最后一个阶段。您只能在$changeStream管道中使用$changeStreamSplitLargeEvent

$changeStreamSplitLargeEvent 事务语法:

{
$changeStreamSplitLargeEvent: {}
}

$changeStreamSplitLargeEvent 将超过16 MB 的事件拆分为片段,并使用变更流游标按顺序返回片段。

分割片段,以便在第一个片段中返回最大数量的字段。这可确保尽快返回事件上下文。

拆分变更事件时,仅使用顶级字段的大小。 $changeStreamSplitLargeEvent不会递归处理或拆分子文档。例如,如果使用$project阶段创建具有大小为20 MB 的单个字段的变更事件,则不会分割该事件,并且该阶段会返回错误。

每个片段都有一个恢复令牌。使用片段令牌恢复的流将:

  • 从后续片段开始一个新流。

  • 如果从序列中的最后一个片段恢复,则从下一个事件开始。

事件的每个片段都包含一个splitEvent文档:

splitEvent: {
fragment: <int>,
of: <int>
}

下表描述了这些字段。

字段
说明
fragment
片段索引,从1开始。
of
事件的片段总数。

本节中的示例场景展示了如何将$changeStreamSplitLargeEvent与名为myCollection的新集合结合使用。

创建myCollection并插入一个包含略低于16 MB 数据的文档:

db.myCollection.insertOne(
{ _id: 0, largeField: "a".repeat( 16 * 1024 * 1024 - 1024 ) }
)

largeField 包含重复的字母a

myCollection启用changeStreamPreAndPostImages ,允许变更流检索更新之前(前映像)和更新之后(后映像)的文档:

db.runCommand( {
collMod: "myCollection",
changeStreamPreAndPostImages: { enabled: true }
} )

使用db.collection.watch()创建变更流游标以监控对myCollection的更改:

myChangeStreamCursor = db.myCollection.watch(
[ { $changeStreamSplitLargeEvent: {} } ],
{ fullDocument: "required", fullDocumentBeforeChange: "required" }
)

对于变更流事件:

  • fullDocument: "required" 包括文档后图像。

  • fullDocumentBeforeChange: "required" 包括文档前像。

有关详细信息,请参阅$changeStream

更新myCollection中的文档,这也会生成包含文档前像和后像的变更流事件:

db.myCollection.updateOne(
{ _id: 0 },
{ $set: { largeField: "b".repeat( 16 * 1024 * 1024 - 1024 ) } }
)

largeField 现在包含重复的字母b

使用next()方法从myChangeStreamCursor检索片段,并将片段存储在名为firstFragmentsecondFragmentthirdFragment的对象中:

const firstFragment = myChangeStreamCursor.next()
const secondFragment = myChangeStreamCursor.next()
const thirdFragment = myChangeStreamCursor.next()

显示firstFragment.splitEvent

firstFragment.splitEvent

包含片段详细信息的输出:

splitEvent: { fragment: 1, of: 3 }

同样, secondFragment.splitEventthirdFragment.splitEvent返回:

splitEvent: { fragment: 2, of: 3 }
splitEvent: { fragment: 3, of: 3 }

要检查firstFragment的对象键:

Object.keys( firstFragment )

输出:

[
'_id',
'splitEvent',
'wallTime',
'clusterTime',
'operationType',
'documentKey',
'ns',
'fullDocument'
]

要检查firstFragment.fullDocument的大小(以字节为单位):

bsonsize( firstFragment.fullDocument )

输出:

16776223

secondFragment 包含fullDocumentBeforeChange前像,大小约为 16 MB。 以下示例显示了secondFragment的对象键:

Object.keys( secondFragment )

输出:

[ '_id', 'splitEvent', 'fullDocumentBeforeChange' ]

thirdFragment 包含updateDescription字段,大小约为 16 MB。以下示例显示了thirdFragment的对象键:

Object.keys( thirdFragment )

输出:

[ '_id', 'splitEvent', 'updateDescription' ]

有关变更流和事件的更多信息,请参阅变更事件。

← $changeStream(聚合)

在此页面上