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

Incorrect counts from bulk write results

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Minor - P4 Minor - P4
    • 2.2.3
    • Affects Version/s: 2.1.2, 2.2.2
    • Component/s: None
    • None
    • Environment:
      MongoDB 2.6

      A bulk write with several `update_one(x,

      {upsert: true}

      )` operations returns a Mongo::BulkWrite::Result with incorrect counts for n_matched and n_upserted. Additionally, there's no public accessor for "n".

      For example, the following reply and result. Note that n_upserted=1 when two documents were upserted, and n_matched=0 when n_modified=1 and n=3.

      [39] pry(#<Mongo::Operation::Write::Bulk::Update::Result>)> @replies
      => [#<Mongo::Protocol::Reply:0x007f813268e470
        @cursor_id=0,
        @documents=
         [{"ok"=>1,
           "nModified"=>1,
           "n"=>3,
           "upserted"=>[{"index"=>0, "_id"=>BSON::ObjectId('56bdf71d72175b828791f84e')}, {"index"=>2, "_id"=>BSON::ObjectId('56bdf71d72175b828791f84f')}]}],
        @flags=[:await_capable],
        @number_returned=1,
        @starting_from=0,
        @upconverter=
         #<Mongo::Protocol::Reply::Upconverter:0x007f8134adb530
          @cursor_id=0,
          @documents=
           [{"ok"=>1,
             "nModified"=>1,
             "n"=>3,
             "upserted"=>[{"index"=>0, "_id"=>BSON::ObjectId('56bdf71d72175b828791f84e')}, {"index"=>2, "_id"=>BSON::ObjectId('56bdf71d72175b828791f84f')}]}],
          @starting_from=0>>]
      

      Result:

      #<Mongo::BulkWrite::Result:0x007f812dc59d28 @results={"n_modified"=>1, "n_upserted"=>1, "n_matched"=>0, "n"=>3, "upserted_ids"=>[BSON::ObjectId('56bdf71d72175b828791f84e'), BSON::ObjectId('56bdf71d72175b828791f84f')]}>
      

      Example BulkWrite operation:

      [11] pry(#<Mongo::BulkWrite::OrderedCombiner>)> requests
      => [{:update_one=>
         {:filter=>
           {:changed_id=>"c0996128-d19a-11e5-a331-80e650068d94",
            :timestamp=>{"$lte"=>1000}},
          :update=>
           {"$set"=>{:timestamp=>1000},
          :upsert=>true}},
       {:update_one=>
         {:filter=>
           {:changed_id=>"c0996128-d19a-11e5-a331-80e650068d94",
            :timestamp=>{"$lte"=>2000}},
          :update=>
           {"$set"=>{:timestamp=>2000},
          :upsert=>true}},
       {:update_one=>
         {:filter=>
           {:changed_id=>"c09e3810-d19a-11e5-a331-80e650068d94",
            :timestamp=>{"$lte"=>3000}},
          :update=>
           {"$set"=>{:timestamp=>3000},
          :upsert=>true}}]
      
      If I understand correctly, the responsible methods are: 
      

      From: /usr/local/var/rbenv/versions/2.0.0-p645/lib/ruby/gems/2.0.0/gems/mongo-2.1.2/lib/mongo/operation/write/bulk/update/result.rb @ line 47 Mongo::Operation::Write::Bulk::Update::Result#n_upserted:

      45: def n_upserted
      46: return 0 unless acknowledged?
      => 47: @replies.reduce(0) do |n, reply|
      48: if upsert?(reply)
      49: n += 1
      50: else
      51: n += 0
      52: end
      53: end
      54: end

      From: /usr/local/var/rbenv/versions/2.0.0-p645/lib/ruby/gems/2.0.0/gems/mongo-2.1.2/lib/mongo/operation/write/bulk/update/result.rb @ line 65 Mongo::Operation::Write::Bulk::Update::Result#n_matched:

      64: def n_matched
      65: return 0 unless acknowledged?
      => 66: @replies.reduce(0) do |n, reply|
      67: if upsert?(reply)
      68: n += 0
      69: else
      70: n += reply.documents.first[N]
      71: end
      72: end
      73: end

      
      

            Assignee:
            emily.stolfo Emily Stolfo
            Reporter:
            john.shearar John Shearar
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: