Summary
The collection::find_one_and_update function appears to ignore the upsert:false option supplied via options::find_one_and_replace.
Environment
Mongo CXX driver version: 4.3.0.
macOS 26.3.1, AARCH64.
Xcode 26.5 and associated clang version (Apple clang version 21.0.0).
Mongo 8.0.3 (Docker image)
How to Reproduce
The following inserts a new document when, if I understand correctly, it should insert nothing (no-op):
{{ __ }}mongocxx::instance inst{};
__ }}mongocxx::client client{mongocxx::uri{"mongodb://localhost:27017";
{{ __ }}auto coll = client["testdb"]["upsert_test"];
{{ __ }}coll.drop();
{{ __ }}coll.insert_one(bsoncxx::from_json(R"({"_id": "x", "field": "original"})"));
{{ __ }}mongocxx::options::find_one_and_update opts;
{{ __ }}opts.upsert(false);
{{ __ }}coll.find_one_and_update(
{{ __ }} bsoncxx::from_json(R"({"_id": "nonexistent"})"),
__ }} bsoncxx::from_json(R"({"$set": {"field": "new")"),
{{ __ }} opts);
Additional Background
I could be mistaken, but I believe the bug is in find_one_and_update_impl in collection.cpp. Specifically, this line:
if (options.upsert()) {
flags = static_cast<mongoc_find_and_modify_flags_t>(flags | MONGOC_FIND_AND_MODIFY_UPSERT);
}
If I'm understanding correctly, the upsert() function returns an optional, which means the upsert flag will get set if the optional has any value (true or false) rather than setting the flag when the optional has a value and that value is true.