Details
Description
Summary
collection::find_one_and_update(), collection::find_one_and_replace(), and collection::find_one_and_delete() accept an optional explicit write concern through the respective option classes: options::find_one_and_update, options::find_one_and_replace, and options::find_one_and_delete. The write concern is incorrectly applied to the command. MongoDB servers prior to 4.2 ignore the incorrectly applied fields, but 4.2+ servers explicitly reject the command.
Any application passing an explicit write concern to the find_one_and_* functions may either upgrade to the patch releases with this fix applied or instead set a write concern on the collection/database object with collection::write_concern() or database::write_concern().
Original description
When journal option for write_concern is specified for find_and_modify (mongocxx v3.5.0 and MongoDB v4.2.6) it throws an error:
terminate called after throwing an instance of 'mongocxx::v_noabi::write_exception'
|
what(): BSON field 'j' is an unknown field.: generic server error
|
Example code:
auto criteria = make_document(kvp("x", "foo"));
|
auto update = make_document(kvp("$set", make_document(kvp("x", "bar"))));
|
|
auto write_concern = mongocxx::write_concern{};
|
write_concern.journal(true);
|
write_concern.acknowledge_level(
|
mongocxx::write_concern::level::k_majority);
|
|
std::cout << "Setting options" << std::endl;
|
auto options = mongocxx::options::find_one_and_update()
|
.write_concern(std::move(write_concern))
|
.return_document(mongocxx::options::return_document::k_before);
|
|
std::cout << "Invoking find_one_and_update" << std::endl;
|
coll.find_one_and_update(
|
criteria.view(),
|
update.view(),
|
options);
|
Looking at the log generated in the server, the options for w and j is not enclosed in writeConcern document. i.e. w: "majority", j: true
2020-05-27T17:31:17.811+1000 I COMMAND [conn7] command dbName.$cmd command: findAndModify { findAndModify: "collectionName", query: { x: "foo" }, update: { $set: { x: "bar" } }, w: "majority", j: true, $db: "test", lsid: { id: UUID("e3fcf2a5-f1c0-4026-b672-c13b27923119") }, txnNumber: 1, $clusterTime: { clusterTime: Timestamp(1590564675, 1), signature: { hash: BinData(0, 0000000000000000000000000000000000000000), keyId: 0 } } } numYields:0 ok:0 errMsg:"BSON field 'j' is an unknown field." errName:Location51177 errCode:51177 reslen:249 locks:{ ParallelBatchWriterMode: { acquireCount: { r: 1 } }, ReplicationStateTransition: { acquireCount: { w: 3 } }, Global: { acquireCount: { r: 2 } }, Database: { acquireCount: { r: 1 } }, Collection: { acquireCount: { r: 1 } }, Mutex: { acquireCount: { r: 1 } } } storage:{} protocol:op_msg 0ms
|
Comparing to find_and_modify sent from PyMongo, the server command log shows {{writeConcern:
{ j: true, w: "majority" }}}
2020-05-27T17:31:10.326+1000 I COMMAND [conn6] command dbName.collectionName command: findAndModify { findAndModify: "collectionName", query: { x: "foo" }, new: false, update: { $set: { x: "bar" } }, upsert: false, writeConcern: { j: true, w: "majority" }, lsid: { id: UUID("296a5316-c756-4099-ba45-e4a14a9380ac") }, txnNumber: 1, $clusterTime: { clusterTime: Timestamp(1590564665, 1), signature: { hash: BinData(0, 0000000000000000000000000000000000000000), keyId: 0 } }, $db: "dbName", $readPreference: { mode: "primary" } } planSummary: EOF keysExamined:0 docsExamined:0 nMatched:0 nModified:0 numYields:0 reslen:217 locks:{ ParallelBatchWriterMode: { acquireCount: { r: 2 } }, ReplicationStateTransition: { acquireCount: { w: 4 } }, Global: { acquireCount: { r: 2, w: 1 } }, Database: { acquireCount: { r: 1, w: 1 } }, Collection: { acquireCount: { r: 2, w: 1 } }, Mutex: { acquireCount: { r: 2 } } } flowControl:{ acquireCount: 1, timeAcquiringMicros: 1 } storage:{} protocol:op_msg 0ms
|
Additional reference: findAndModify
Looking at the server code, a change is introduced by SERVER-40005 to check for unknown field in find_and_modify. https://github.com/mongodb/mongo/blame/r4.2.6/src/mongo/db/query/find_and_modify_request.cpp#L252
(Similar error is not thrown on MongoDB v4.0.x)
Â