Repository navigation
Conversation
f41939a to
a272516
Compare
0cffb0a to
897a61b
Compare
|
Hi team! I've added a dedicated unit and integration tests (output_test.go) inside the internal mongodb package to verify this change using testcontainers. The test successfully passes and confirms that Go-native []byte fields are now correctly preserved and stored as native bson.Binary (BinData) inside MongoDB instead of being forced into base64 strings. Regarding backward compatibility: since this alters the data type stored in the database for raw bytes, please let me know if we should safely gate this behind a new configuration flag (like preserve_binary: false by default), or if you prefer to accept this as the correct default behavior for the connector. Ready for your review! |
897a61b to
b62b80c
Compare
|
Update: I went ahead and implemented the |
1a78989 to
630bfa0
Compare
|
Hi @mmatczuk, could you please take a look when you have a moment? |
630bfa0 to
b58db1e
Compare
b58db1e to
8b67235
Compare
|
Hi team! I've just rebased the branch with the latest main to ensure everything is up to date and all tests/CI pass smoothly. Since this fixes a silent data type mutation issue in MongoDB (saving raw bytes as base64), it would be great to get this reviewed when you have a moment. Thanks! |
There was a problem hiding this comment.
You can already store native BinData with document_map, without a new option.
The output reads the result of document_map as MongoDB extended JSON. In extended JSON, binary data uses $binary.
Example 1: the message is raw bytes
Each Kafka record is a file. We store the full record as BinData:
input:
redpanda:
seed_brokers: [ localhost:9092 ]
topics: [ files ]
consumer_group: mongo_writer
output:
mongodb:
url: mongodb://localhost:27017
database: example
collection: files
operation: insert-one
document_map: |
root.name = metadata("kafka_key")
root.content = {
"$binary": {
"base64": content().encode("base64"),
"subType": "00"
}
}Example 2: the message is JSON with a base64 field
The field is already base64, so we do not encode it again:
input:
generate:
count: 1
mapping: |
root.id = "img-1"
root.thumbnail = "iVBORw0KGgo="
output:
mongodb:
url: mongodb://localhost:27017
database: example
collection: images
operation: insert-one
document_map: |
root._id = this.id
root.thumbnail = { "$binary": { "base64": this.thumbnail, "subType": "00" } }In both examples, MongoDB stores the field as BinData (subtype 0). If you write raw bytes instead (for example root.content = content()), you get a base64 string. This is how JSON writes bytes, and it is the documented behavior.
I also found some problems with preserve_binary: true:
-
It stops extended JSON for the full document, not only for binary fields. For example, with this mapping:
document_map: | root.created_at = { "$date": { "$numberLong": "1700000000000" } }
MongoDB stores
created_atas an object with a$datekey, not as a date.$oidand$numberDecimalhave the same problem. -
The field order of the document can change, because the document becomes a Go map.
-
filter_mapandhint_mapstill use extended JSON. So the same config can mean two different things.
Because of this, I prefer not to add the option.
But a $binary example in the document_map docs would help other users who have this problem. Would you be open to change the PR to add that example (or open a new one)? The docs come from the field description in internal/impl/mongodb/common.go.
Sidenote: the docs/modules/ files are generated, so you can remove your changes to them.
|
Hi @Leward, Thank you for the detailed feedback and for catching the regressions with Previously, the connector relied on While your suggested manual workaround using To solve this properly, I propose to refine the PR as follows:
This eliminates the need for manual configuration boilerplates for binary payloads while keeping the connector completely stable and backward-compatible. What do you think about this adjusted direction? If it sounds good, I will refactor the code to fix the regressions and cover all mapping modes. |
5bf54d4 to
819bfdb
Compare
…handling Introduced a new configuration option `preserve_binary` (defaulting to `false`) for MongoDB output, filters, hints, and processor components. When enabled, it ensures that Go-native `[]byte` fields (e.g., from decoded Protobuf/Avro payloads) are correctly stored as BSON native `BinData` instead of being mutated into base64 strings. This allows users to opt-in correct binary data representation while completely maintaining backward compatibility for existing deployments by default. Refactored the internal mapping logic from a heavy document-wide string serialization/deserialization to a optimized, single-pass in-place traversal over `msg.AsStructured()`. Added integration tests for both output and processor to cover new behavior and verify data types validation on live MongoDB instances.
819bfdb to
f2c7fb9
Compare
|
Hi @Leward, Thanks for the feedback! I have fully refactored the code to address your concerns. The regressions should be fixed now. Regarding the documentation: I also tried to update the When I add them to Could you please point me to the specific line/function where I should inject these structured component-level examples? Or, if it's easier, feel free to push that documentation piece directly to this branch. Thanks again for your help! |
Fixed an issue where binary data (
[]byte) was always serialized as abase64string in MongoDB. This occurred because the output plugin was converting the structure to a JSON string and then re-parsing it using theextJSONparser, which loses the native binary type.Replaced
extJSONFromMapwithstructuredFromMapleveragingmsg.AsStructured(). This prevents immediate string serialization and preserves native Go slices, enabling the MongoDB driver to properly handle binary payloads.Backward Compatibility
To maintain full backward compatibility and prevent breaking downstream client applications, the old serialization behavior (saving binary fields as base64 strings) is kept by default.
A new configuration option,
preserve_binary(defaulting tofalse), has been introduced for both MongoDB output and processor components. Users can set this flag totrueto opt-in to the correct native BSONBinDatarepresentation.Some integration and unit tests have been added to verify both the default and new execution paths.