Uploaded image for project: 'Ruby Driver'
  1. Ruby Driver
  2. RUBY-3355

Create when key '_id' (as string) is nil results in error

    • Type: Icon: Task Task
    • Resolution: Unresolved
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: 2.19.2
    • Component/s: CRUD

      Reported on GitHub with PR - https://github.com/mongodb/mongo-ruby-driver/pull/2808

      While investigating an issue in an application I'm working on I discovered that trying to insert a document containing '_id' => nil will raise the following exception:

      .../lib/mongo/operation/result.rb:364:in `raise_operation_failure': [2]: can't have multiple _id fields in one document (on 127.0.0.1:27017, legacy retry, attempt 1) (Mongo::Error::OperationFailure)
      

      Here's a reproduction script:

      require 'bundler/inline'
      
      gemfile do
        source 'https://rubygems.org'
        gem 'mongo'
      end
      
      client = Mongo::Client.new(['127.0.0.1:27017'], database: 'PoC_DTM') # Assuming you have a mongo server running on port 27017
      db = client.database
      collection = db[:fake_collection]
      
      collection.insert_one({ field: 'test', _id: nil }) # => OK
      collection.insert_one({ field: 'test', '_id' => nil }) # => KO
      

      I was able to track down the issue in the lib/mongo/operation/shared/idable.rb file:

      ...
            def id(doc)
              doc.respond_to?(:id) ? doc.id : (doc['_id'] || doc[:_id])
            end
      
            def has_id?(doc)
              !!id(doc)
            end
      
            def ensure_ids(documents)
              @ids= []
              documents.collect do |doc|
                doc_with_id = has_id?(doc) ? doc : doc.merge(_id: id_generator.generate)
                @ids<< id(doc_with_id)
                doc_with_id
              end
            end
      ...
      

      When '_id' is equal to nil has_id? returns false which causes ensure_ids to generate an id that it stores in :_id but without removing the '_id' key which results in the document having both '_id' and :_id, hence the exception mentioned above.

            Assignee:
            Unassigned Unassigned
            Reporter:
            jamis.buck@mongodb.com Jamis Buck
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated: