$changeStreamSplitLargeEvent (agregação)
Nesta página
Definição
Novidade no MongoDB 7.0 (e 6.0.9).
Se umchange stream tiver eventos grandes que excedam 16 MB, uma exceção BSONObjectTooLarge
será retornada. A partir do MongoDB 7.0 (e 6.0.9), você pode utilizar um estágio $changeStreamSplitLargeEvent
para divisão os eventos em fragmentos menores.
Você só deve usar $changeStreamSplitLargeEvent
quando estritamente necessário. Por exemplo, se seu aplicativo exigir imagens pré ou pós-documento completo e gerar eventos grandes que excedam 16 MB, use $changeStreamSplitLargeEvent
.
Antes de decidir usar $changeStreamSplitLargeEvent
, você deve primeiro tentar reduzir o tamanho do evento de alteração. Por exemplo:
Não solicite pré ou pós-imagens de documentos, a menos que seu aplicativo as exija. Isso gera campos
fullDocument
efullDocumentBeforeChange
em mais casos, que normalmente são os maiores objetos em um evento de alteração.Use um estágio
$project
a fim de incluir apenas os campos necessários para sua aplicação. Isso reduz o tamanho do evento de alteração e evita o tempo adicional para dividir eventos grandes em fragmentos. Assim, mais eventos de alteração podem ser retornados em cada lote.
Você só pode ter um estágio $changeStreamSplitLargeEvent
no seu pipeline, e ele deve ser o último. Você só pode usar $changeStreamSplitLargeEvent
em um pipeline $changeStream
.
$changeStreamSplitLargeEvent
sintaxe:
{ $changeStreamSplitLargeEvent: {} }
Comportamento
$changeStreamSplitLargeEvent
divide eventos que excedem 16 MB em fragmentos e retorna os fragmentos sequencialmente usando o cursor de fluxo de alterações.
Os fragmentos são divisão para que o número máximo de campos seja retornado no primeiro fragmento. Isso garante que o contexto do evento seja retornado o mais rápido possível.
Quando o evento de alteração é dividido, somente o tamanho dos campos de nível superior é usado. $changeStreamSplitLargeEvent
não processa nem faz a divisão de subdocumentos recursivamente. Por exemplo, se você usar um estágio $project
para criar um evento de alteração com um único campo que tem 20 MB de tamanho, o evento não sofrerá uma divisão, e o estágio retornará um erro.
Cada fragmento possui um token de retomada. Um stream retomado usando o token de um fragmento irá:
Iniciar um novo fluxo a partir do fragmento subsequente.
Comece no próximo evento se continuar a partir do fragmento final da sequência.
Cada fragmento de um evento inclui um documento splitEvent
:
splitEvent: { fragment: <int>, of: <int> }
A tabela a seguir descreve os campos.
Campo | Descrição |
---|---|
fragment | Índice de fragmento, a partir de 1. |
of | Número total de fragmentos do evento. |
Exemplo
O cenário de exemplo nesta seção mostra o uso de $changeStreamSplitLargeEvent
com uma nova coleção denominada myCollection
.
Crie myCollection
e insira um documento com pouco menos 16 MB de dados:
db.myCollection.insertOne( { _id: 0, largeField: "a".repeat( 16 * 1024 * 1024 - 1024 ) } )
largeField
contém a letra repetida a
.
Ative ChangeStreamPreandPostImages para myCollection
, o que permite que um fluxo de alterações recupere um documento como estava antes de uma atualização (pré-imagem) e depois de uma atualização (pós-imagem):
db.runCommand( { collMod: "myCollection", changeStreamPreAndPostImages: { enabled: true } } )
Crie um cursor de fluxo de alterações para monitorar as alterações em myCollection
usando db.collection.watch()
:
myChangeStreamCursor = db.myCollection.watch( [ { $changeStreamSplitLargeEvent: {} } ], { fullDocument: "required", fullDocumentBeforeChange: "required" } )
Para o evento de fluxo de alterações:
fullDocument: "required"
inclui a pós-imagem do documento.fullDocumentBeforeChange: "required"
inclui a pré-imagem do documento.
Para detalhes, consulte $changeStream
.
Atualize o documento em myCollection
, que também produz um evento de fluxo de alteração com as imagens pré e pós do documento :
db.myCollection.updateOne( { _id: 0 }, { $set: { largeField: "b".repeat( 16 * 1024 * 1024 - 1024 ) } } )
largeField
agora contém a letra repetida b
.
Recupere os fragmentos de myChangeStreamCursor
usando o método next()
e armazene os fragmentos em objetos chamados firstFragment
, secondFragment
e thirdFragment
:
const firstFragment = myChangeStreamCursor.next() const secondFragment = myChangeStreamCursor.next() const thirdFragment = myChangeStreamCursor.next()
Mostrar firstFragment.splitEvent
:
firstFragment.splitEvent
Saída com os detalhes do fragmento:
splitEvent: { fragment: 1, of: 3 }
Da mesma forma, secondFragment.splitEvent
e thirdFragment.splitEvent
retornam:
splitEvent: { fragment: 2, of: 3 } splitEvent: { fragment: 3, of: 3 }
Para examinar as chaves de objeto para firstFragment
:
Object.keys( firstFragment )
Saída:
[ '_id', 'splitEvent', 'wallTime', 'clusterTime', 'operationType', 'documentKey', 'ns', 'fullDocument' ]
Para examinar o tamanho em bytes de firstFragment.fullDocument
:
bsonsize( firstFragment.fullDocument )
Saída:
16776223
secondFragment
contém a pré-imagem fullDocumentBeforeChange
, que tem aproximadamente 16 MB de tamanho. O exemplo a seguir mostra as chaves de objeto para secondFragment
:
Object.keys( secondFragment )
Saída:
[ '_id', 'splitEvent', 'fullDocumentBeforeChange' ]
thirdFragment
contém o campo updateDescription
, que tem aproximadamente 16 MB de tamanho. O exemplo a seguir mostra as chaves de objeto para thirdFragment
:
Object.keys( thirdFragment )
Saída:
[ '_id', 'splitEvent', 'updateDescription' ]
Para obter mais informações sobre fluxos e eventos de alteração, consulte Alterar eventos.