oscar oscar - 4 months ago 34
Ruby Question

how to handle mongodb's E11000 duplicate key error in ruby

Is there any good example of handling mongodb related exceptions in ruby?
In this case I have:

/home/askar/.rvm/gems/ruby-1.9.3-p429/gems/mongo-1.8.6/lib/mongo/networking.rb:89:in `send_message_with_gle': 11000: E11000 duplicate key error index: somedb.somecoll.$_id_ dup key: { : "some_id" } (Mongo::OperationFailure)
from /home/askar/.rvm/gems/ruby-1.9.3-p429/gems/mongo-1.8.6/lib/mongo/collection.rb:1108:in `block in insert_documents'
from /home/askar/.rvm/gems/ruby-1.9.3-p429/gems/mongo-1.8.6/lib/mongo/util/logging.rb:33:in `block in instrument'
from /home/askar/.rvm/gems/ruby-1.9.3-p429/gems/mongo-1.8.6/lib/mongo/util/logging.rb:65:in `instrument'
from /home/askar/.rvm/gems/ruby-1.9.3-p429/gems/mongo-1.8.6/lib/mongo/util/logging.rb:32:in `instrument'
from /home/askar/.rvm/gems/ruby-1.9.3-p429/gems/mongo-1.8.6/lib/mongo/collection.rb:1106:in `insert_documents'
from /home/askar/.rvm/gems/ruby-1.9.3-p429/gems/mongo-1.8.6/lib/mongo/collection.rb:375:in `insert'
from lib/tasks/getorders.rb:47:in `block in <main>'
from lib/tasks/getorders.rb:25:in `each'
from lib/tasks/getorders.rb:25:in `<main>'


I'm having this error because I'm trying to insert a document with the id that already exists in mongodb database, I just want to know how to handle mongodb related exceptions in ruby.
For example, if an exception occurs, then I would change the id of the hash and then re-try to insert it.

How rescue block would look like?

Answer

The ruby block would look something like :

begin
  # your operation
rescue Mongo::OperationFailure => e
  if e.message =~ /^11000/
    puts "Duplicate key error #{$!}"
    # do something to recover from duplicate
  else
    raise e
  end
end
# the rest of the exceptions follow ..
# if you just care about the dup error
# then ignore them
#rescue Mongo::MongoRubyError
#  #Mongo::ConnectionError, Mongo::ConnectionTimeoutError, Mongo::GridError, Mongo::InvalidSortValueError, Mongo::MongoArgumentError, Mongo::NodeWithTagsNotFound
#  puts "Ruby Error :  #{$!}"
#rescue Mongo::MongoDBError
#  # Mongo::AuthenticationError, Mongo::ConnectionFailure, Mongo::InvalidOperation, Mongo::OperationFailure
#  puts "DB Error :  #{$!}"
#rescue Mongo::OperationTimeout
#  puts "Socket operation timeout Error :  #{$!}"
#rescue Mongo::InvalidNSName
#  puts "invalid collection or database Error :  #{$!}"
#end

But, if you are updating a record that already exists, why not you use an upsert.

If you are creating a new record then why not let the mongod create the _id ?