[SERVER-59132] Improve $merge failure when matched error message Created: 05/Aug/21  Updated: 29/Oct/23  Resolved: 22/Nov/21

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: 5.2.0

Type: Improvement Priority: Major - P3
Reporter: Alice Thum Assignee: Hana Pearlman
Resolution: Fixed Votes: 0
Labels: neweng, quick-tech-debt
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Backwards Compatibility: Fully Compatible
Participants:

 Description   

When executing a $merge with a whenMatched: fail option specified, the error message can be misleading. See the following example:

> db.source.find()
{ "_id" : 1, "a" : 2, "b" : 3, "c" : 4 }
{ "_id" : 2, "a" : 3, "b" : 4, "c" : 5 }
{ "_id" : 3, "a" : 4, "b" : 5, "c" : 6 }
> db.target.find()
{ "_id" : 1, "a" : 2, "black" : "sheep" }
> db.source.aggregate([
...   {
...     $merge: {
...       into: "target",
...       on: "a",
...       whenMatched: "fail",
...       whenNotMatched: "insert"
...     }
...   }
... ])
uncaught exception: Error: command failed: {
        "ok" : 0,
        "errmsg" : "E11000 duplicate key error collection: playground.target index: _id_ dup key: { _id: 1.0 }",
        "code" : 11000,
        "codeName" : "DuplicateKey",
        "keyPattern" : {
                "_id" : 1
        },
        "keyValue" : {
                "_id" : 1
        }
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:618:17
assert.commandWorked@src/mongo/shell/assert.js:708:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1046:12
@(shell):1:1

Instead of elucidating that the operation failed because a document in the source matched one in the target collection, a duplicate key error is returned.

The error message should be updated to indicate that this is expected due to the documents matching in this case.



 Comments   
Comment by Githook User [ 22/Nov/21 ]

Author:

{'name': 'Hana Pearlman', 'email': 'hana.pearlman@mongodb.com', 'username': 'HanaPearlman'}

Message: SERVER-59132: Improve error message for $merge with whenMatched: fail
Branch: master
https://github.com/mongodb/mongo/commit/08ed50a5e31392a9bf90c5d450941ff9c281740b

Comment by Charlie Swanson [ 26/Aug/21 ]

Throwing this on the backlog - I think we could reasonably detect when the duplicate key is on the "on" field and give a more useful error message indicating that we are failing because you asked us to fail in this scenario, not because something else went wrong.

Comment by Alice Thum [ 19/Aug/21 ]

I was thinking it would be nice to see something similar to "$merge could not find a matching document in the target collection for at least one document in the source collection" - which is what gets returned when { "whenNotMatched": fail }. It would be easier to glean that it was not user error (e.g. duplicate ids or keys) that caused the operation to fail, but rather that we found a matching document - this would especially be helpful in a larger collection with more complicated schema/$merge parameters.

That being said, it seems like this wouldn't work super well for the server's internal $merge implementation so I'm fine closing this ticket if there's no clear path to expose something like that!

Comment by Charlie Swanson [ 19/Aug/21 ]

Got it, thanks! Do you think adding some context like this would be good enough?

uncaught exception: Error: command failed: {
        "ok" : 0,
        "errmsg" : "error while executing insert for $merge {into: "target", on: "a", whenMatched: "fail", whenNotMatched: "insert"}: E11000 duplicate key error collection: playground.target index: a_1 dup key: { a: 2.0 }",
        "code" : 11000,
        "codeName" : "DuplicateKey",
        "keyPattern" : {
                "a" : 1
        },
        "keyValue" : {
                "a" : 2
        }
}
 

Or were you hoping to see specifically some text around "the target value was found and you specified to error"? I think your example with _id shows how it could be tricky - we can't necessarily use DuplicateKey as evidence that we found a match. It may be possible but it's not obvious to me.

Comment by Alice Thum [ 19/Aug/21 ]

I changed the "_id" of the document in the target collection to 4, so all "_id"s would be unique. The same query then fails with

uncaught exception: Error: command failed: {
        "ok" : 0,
        "errmsg" : "E11000 duplicate key error collection: playground.target index: a_1 dup key: { a: 2.0 }",
        "code" : 11000,
        "codeName" : "DuplicateKey",
        "keyPattern" : {
                "a" : 1
        },
        "keyValue" : {
                "a" : 2
        }
}

Comment by Charlie Swanson [ 19/Aug/21 ]

alice.thum it looks like the duplicate key is coming from the id, not the "a" field which is the one given as the "on" option. If there is a duplicate key only on "a", is the error message any better/different?

Generated at Thu Feb 08 05:46:26 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.