Hi @TopherGopher!
Three more things that are being added to this API are ServerError.HasMessage(string) to check for a message substring, ServerError.HasErrorCodeWithMessage(int, string) to check for a message substring on errors with a specific code, and a standalone IsNetworkError(error) to check if errors are network errors.
The goal of the standalone helpers is to handle all cases where multiple error representations benefit from being linked, so a user wouldn’t be expected to know all the historical ways IsDuplicateKey error could be represented. It’s only Duplicate Key errors right now, but any errors in the future require more complex logic, they would also get helpers.
We don’t want to set up our own go driver error categories because setting up our own categories requires us to maintain them on fairly unstable server error codes. While we’re happy to add standalone helpers for checking for useful groups of errors, I’m not sure of the benefit of these specific categories. Many of the errors in each category wouldn’t occur together, and wouldn’t necessarily want to be handled the same way. I’m also not sure of the benefit of knowing that an error is, for example, a bad input parameter without knowing what’s wrong with which parameter. Do you have a specific use case you’re thinking of for these?
As an additional note, there is a ticket to add the error codes to the documentation, which should make them easier to find, but as of right now, that server file is the best source.
For the case that you’re describing, you could instead do:
if mErr, ok := err.(mongo.ServerError); ok {
If mErr.HasErrorCodeWithMessage(2, "must be an array but is of type null") {
// Perform a $set rather than $push
}
}
For your specific use case, the issue is that nil slices get marshaled to BSON null values, so myArray in your collection may either be an array or null. You could avoid mixing null and array by using a custom registry or aggregation updates. To work around this with a custom registry, you would use a registry with a SliceCodec with SetEncodeNilAsArray(true). Alternatively, to work around this with aggregation updates, you would use aggregation to conditionally append or set.
For example, on a collection that contains {x: null} and {x: [1,2]}, you could append or set x to [3] with the following:
var pipeline = mongo.Pipeline{
bson.D{
{"$set", bson.D{
{"x", bson.D{
{"$concatArrays", bson.A{
bson.D{{"$ifNull", bson.A{"$x", bson.A{}}}},
bson.A{3},
}},
}},
}},
},
}
res, err := coll.UpdateMany(context.Background(), bson.D{}, pipeline)