Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With mongodb-go-driver how do I get the inner exceptions

Tags:

mongo-go

When I insert into a collection with the new MongoDB Go driver I get a duplicate exception that I can see when spewing it. (mongo.WriteException) multiple write errors:

[{write errors: [{E11000 duplicate key error collection: fhir.documents index: enterprise_id_1 dup key: { : "Cache-37", : "102" }}]}, {}]

How do I get to that inner error to programatically know that it was a duplicate key and I can handle it?

like image 345
Donald French Avatar asked Jul 06 '19 19:07

Donald French


3 Answers

You saved me a headache with this. Building on from your own answer I made a helper function that imitates mgo.IsDup() using errors.As and looping over the WriteErrors to find code 11000.

func IsDup(err error) bool {
    var e mongo.WriteException
    if errors.As(err, &e) {
        for _, we := range e.WriteErrors {
            if we.Code == 11000 {
                return true
            }
        }
    }
    return false
}

I have it in my database package so I can just call db.IsDup(err)

I suppose if I need it i'll just abstract the loop to check for more error codes but at least this way I can migrate from mgo with a little less trouble.

like image 179
Jordan Whitfield Avatar answered Oct 12 '22 16:10

Jordan Whitfield


Nowadays in [email protected] we have the following function defined in mongo/errors.go:

// IsDuplicateKeyError returns true if err is a duplicate key error
func IsDuplicateKeyError(err error) bool {
    // handles SERVER-7164 and SERVER-11493
    for ; err != nil; err = unwrap(err) {
        if e, ok := err.(ServerError); ok {
            return e.HasErrorCode(11000) || e.HasErrorCode(11001) || e.HasErrorCode(12582) ||
                e.HasErrorCodeWithMessage(16460, " E11000 ")
        }
    }
    return false
}

So we can rely on the mongo-driver implementation.

like image 21
drocha87 Avatar answered Oct 12 '22 15:10

drocha87


I finally found out how. It should be much simpler to get the basic error codes! Given an error, I check for the number of errors found and currently only care about the first one. Even though the initial error says multiple errors, it only has one. This is really only looking for Insert failures of duplicate or Find errors of not found. If there is an easier way, I would like to know. Until then this is what I am using and it works fine. Duplicate by the way is 11000.

"Insert with session failed: multiple write errors: [{write errors: [{E11000 duplicate key error collection: test.users index: roi_id_1 dup key: { : \"1\" }}]}, {}]\n"

        var merr mongo.WriteException
        merr = err.(mongo.WriteException)
        log.Errorf("Number of errors: %d", len(merr.WriteErrors))
        errCode := merr.WriteErrors[0].Code
like image 28
Donald French Avatar answered Oct 12 '22 15:10

Donald French