【问题标题】:how to handle mongodb's E11000 duplicate key error in ruby如何在ruby中处理mongodb的E11000重复键错误
【发布时间】:2013-05-31 14:03:14
【问题描述】:

有没有在 ruby​​ 中处理 mongodb 相关异常的好例子? 在这种情况下,我有:

/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>'

我遇到这个错误是因为我试图插入一个 id 已经存在于 mongodb 数据库中的文档,我只想知道如何在 ruby​​ 中处理与 mongodb 相关的异常。 比如,如果发生异常,那么我会更改哈希的id,然后重新尝试插入。

rescue块是什么样子的?

【问题讨论】:

    标签: ruby mongodb exception-handling error-handling


    【解决方案1】:

    红宝石块看起来像:

    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
    

    但是,如果您要更新已存在的记录,为什么不使用upsert

    如果您要创建新记录,那么为什么不让 mongod 创建 _id 呢?

    【讨论】:

    • 嗨!我故意在 ruby​​ 的哈希中创建 _id,然后用这个 _id 创建一个文档。 _id 基于我下载的文件创建。因此,如果发生 _id dup 错误,它将给我一个信号,表明我将下载相同的文件。与其搜索 mongodb 数据库中的所有文档以检查是否已经存在具有相同 _id 的记录,我认为最好将其捕获异常并进行进一步操作,不要下载或更改此 dup 记录的 _id。感谢您的回答!
    • 注意:最新的 Ruby 驱动程序将错误暴露为 Mongo::Error::OperationFailure。
    • 添加到@Joerg 的评论中,使用最新驱动程序的 e.message 的正则表达式应该是 /^E11000/
    【解决方案2】:

    也可以使用写关注点。

    @mongo_client.save({:doc =&gt; 'foo'}, {:w =&gt; 0}) # writes are not acknowledged

    虽然这不如救援。

    【讨论】:

      【解决方案3】:

      如果您的 ruby​​ 驱动程序是 &gt;= 2.0.0,您应该使用 Mongo::Error 类来处理大多数与 mongodb 相关的异常。以下是您的 rescue 块的外观:

      begin
        # Document insert code
      rescue Mongo::Error => e
        if e.message.include? 'E11000'
          # Change the id of the hash & re-try to insert it
        end
      end
      

      【讨论】:

        猜你喜欢
        • 2017-02-20
        • 2018-10-12
        • 2019-05-03
        • 1970-01-01
        • 1970-01-01
        • 2018-10-13
        • 2018-01-19
        相关资源
        最近更新 更多