We recently added MongoChangeStreamMBS class to MBS Xojo Plugins to watch changes in the database. You can monitor a database, a collection or the whole system. We show you today on how to use that in Xojo.
First, we change the local copy of MongoDB installed via homebrew on your Mac to allow the use of change streams. For that you need to make sure the replica set is activated. First check “/etc/mongod.conf” file to add the replSetName entry:
replication:
replSetName: "replicaset-01"
Then we restart the MongoDB service here:
brew services restart mongodb/brew/mongodb-community
Next we connect via mongosh and then run this command:
rs.initiate()
And now we have a replica set with one node. Now we need to connect and disable retry writes with an extra parameter in the URL:
mongodb://localhost/?retryWrites=false
Once we got everything in position to use a change stream, we can try the code below. First we create the change stream by watching the collection. The pipeline parameter allows you to specify a filter on what to watch. Next, we insert a record and query the stream for the change report:
Sub Insert()
// start streaming
Dim pipeline As String = "{}"
Dim stream As MongoChangeStreamMBS = Collection.Watch(pipeline)
// add a new record
Dim NewRecord As New JSONItem
NewRecord.Value("firstName") = "Bob"
NewRecord.Value("lastName") = "Jones"
NewRecord.Value("phone") = "555-1234-567"
Dim Result As String = Collection.InsertOne(NewRecord.toString)
// and now query changes
Dim changeJSON As String
While stream.NextChange(changeJSON)
Break
Wend
End Sub
While this example does all in one method, you can of course split this. Do the change stream when the application launches and monitor all changes while you may do various edits in the same or another application.
The insert operation returns us this JSON:
{ "insertedCount" : 1 }
And the change is reported like the following. As you see the whole document is included there with the entries for which database and collection is used.
{
"_id": {
"_data": "82638DBEAA000...
},
"operationType": "insert",
"clusterTime": {
"$timestamp": {
"t": 1670233770,
"i": 2
}
},
"wallTime": {
"$date": "2022-12-05T09:49:30.372Z"
},
"fullDocument": {
"_id": {
"$oid": "638dbeaac200714b55005291"
},
"firstName": "Bob",
"lastName": "Jones",
"phone": "555-1234-567"
},
"ns": {
"db": "test",
"coll": "test"
},
"documentKey": {
"_id": {
"$oid": "638dbeaac200714b55005291"
}
}
}
Now we update the record with a similar method:
Sub Update()
// start streaming
Dim pipeline As String = "{}"
Dim stream As MongoChangeStreamMBS = Collection.Watch(pipeline)
// update an existing record
Dim ChangedRecord As New JSONItem
ChangedRecord.Value("firstName") = "Bob"
ChangedRecord.Value("lastName") = "Miller"
ChangedRecord.Value("phone") = "555-1234-567"
dim SetRecord as new JSONItem
SetRecord.Value("$set") = ChangedRecord
dim condRecord as new JSONItem
condRecord.Value("firstName") = "Bob"
Dim Result As String = Collection.UpdateOne(condRecord.ToString, SetRecord.toString)
// and now query changes
Dim changeJSON As String
While stream.NextChange(changeJSON)
Break
Wend
End Sub
The update operation returns a JSON like this to report that one record matched and one record was changed:
{ "modifiedCount" : 1, "matchedCount" : 1, "upsertedCount" : 0 }
The change stream reports the update operation with the following JSON. Now the whole document is not included, but it lists which field got updated and the new name:
{
"_id": {
"_data": "82638DC032000000...
},
"operationType": "update",
"clusterTime": {
"$timestamp": {
"t": 1670234162,
"i": 1
}
},
"wallTime": {
"$date": "2022-12-05T09:56:02.607Z"
},
"ns": {
"db": "test",
"coll": "test"
},
"documentKey": {
"_id": {
"$oid": "638dbeaac200714b55005291"
}
},
"updateDescription": {
"updatedFields": {
"lastName": "Miller"
},
"removedFields": [],
"truncatedArrays": []
}
}
Please try the MongoChangeStreamMBS class and let us know how you like it.