Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-3780

Eager loading does not work with _id fields of BSON::Binary type

    • Type: Icon: Task Task
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • 5.0.2
    • Affects Version/s: None
    • Component/s: None
    • Labels:
      None

      If you try to use has_and_belongs_to_many eager loading with dependent objects having _id field of type BSON::Binary you get empty arrays instead of children. Mongoid does perform a single query to load all these objects, but then doesn't seem to be able to find results and performs additional queries with nil instead of actual children IDs. This seems to be something specific to Binary fields, because IDs of type String work just as well as regular ObjectId type.

      Test script:

      #gem "mongoid", "=3.1.6"
      gem "mongoid", "=4.0.0"
      
      require "mongoid"
      
      puts "Using Mongoid #{Mongoid::VERSION}"
      
      Mongoid.configure {|c| c.connect_to "test"}
      
      def verbose
        old_logger = Moped.logger
        Moped.logger = Logger.new(STDOUT)
        puts "\n\n"
        yield
      ensure
        Moped.logger = old_logger
      end
      
      class Parent
        include Mongoid::Document
        has_and_belongs_to_many :children, inverse_of: nil
      end
      
      class Child
        include Mongoid::Document
        field :_id, type: BSON::Binary, default: -> {
          BSON::Binary.new SecureRandom.hex(3)
        }
        field :something, type: Integer, default: -> {rand(1_000)}
      end
      
      Parent.delete_all
      3.times do
        parent = Parent.create
        5.times do
          parent.children << Child.create
        end
      end
      
      verbose do
        puts "Without eager loading"
        Parent.all.each {|p| puts p.children.map(&:something).inspect}
      end
      
      verbose do
        puts "With eager loading"
        Parent.all.includes(:children).each {|p| puts p.children.map(&:something).inspect}
      end
      

      Output:

      mongoid-errors$ruby eager_load.rb 
      Using Mongoid 4.0.0
      W, [2014-08-24T02:22:12.058385 #95340]  WARN -- : Overwriting existing field _id in class Child.
      
      
      Without eager loading
      D, [2014-08-24T02:22:12.088171 #95340] DEBUG -- :   MOPED: 127.0.0.1:27017 QUERY        database=test collection=parents selector={} flags=[] limit=0 skip=0 batch_size=nil fields=nil runtime: 0.3770ms
      D, [2014-08-24T02:22:12.089165 #95340] DEBUG -- :   MOPED: 127.0.0.1:27017 QUERY        database=test collection=children selector={"$and"=>[{"_id"=>{"$in"=>[#<BSON::Binary:0x007f7f7aa88e90 @data="64d53e", @type=:generic>, #<BSON::Binary:0x007f7f7aa88c88 @data="6ed747", @type=:generic>, #<BSON::Binary:0x007f7f7aa888f0 @data="be81ff", @type=:generic>, #<BSON::Binary:0x007f7f7aa88710 @data="e950c4", @type=:generic>, #<BSON::Binary:0x007f7f7aa88580 @data="7da04e", @type=:generic>]}}]} flags=[] limit=0 skip=0 batch_size=nil fields=nil runtime: 0.4480ms
      [201, 753, 564, 497, 433]
      D, [2014-08-24T02:22:12.090226 #95340] DEBUG -- :   MOPED: 127.0.0.1:27017 QUERY        database=test collection=children selector={"$and"=>[{"_id"=>{"$in"=>[#<BSON::Binary:0x007f7f7aa88008 @data="56fe72", @type=:generic>, #<BSON::Binary:0x007f7f7aa7be98 @data="9a6cdf", @type=:generic>, #<BSON::Binary:0x007f7f7aa7bd58 @data="96956e", @type=:generic>, #<BSON::Binary:0x007f7f7aa7bc40 @data="c8e19d", @type=:generic>, #<BSON::Binary:0x007f7f7aa7ba38 @data="7e7f2e", @type=:generic>]}}]} flags=[] limit=0 skip=0 batch_size=nil fields=nil runtime: 0.4310ms
      [21, 167, 84, 450, 195]
      D, [2014-08-24T02:22:12.091216 #95340] DEBUG -- :   MOPED: 127.0.0.1:27017 QUERY        database=test collection=children selector={"$and"=>[{"_id"=>{"$in"=>[#<BSON::Binary:0x007f7f7aa7b5b0 @data="0b98dd", @type=:generic>, #<BSON::Binary:0x007f7f7aa7b470 @data="32c896", @type=:generic>, #<BSON::Binary:0x007f7f7aa7b358 @data="5b0738", @type=:generic>, #<BSON::Binary:0x007f7f7aa7b218 @data="693c6d", @type=:generic>, #<BSON::Binary:0x007f7f7aa7b060 @data="4d2996", @type=:generic>]}}]} flags=[] limit=0 skip=0 batch_size=nil fields=nil runtime: 0.4080ms
      [845, 431, 694, 885, 190]
      
      
      With eager loading
      D, [2014-08-24T02:22:12.092050 #95340] DEBUG -- :   MOPED: 127.0.0.1:27017 QUERY        database=test collection=parents selector={} flags=[] limit=0 skip=0 batch_size=nil fields=nil runtime: 0.3240ms
      D, [2014-08-24T02:22:12.093532 #95340] DEBUG -- :   MOPED: 127.0.0.1:27017 QUERY        database=test collection=children selector={"_id"=>{"$in"=>[#<BSON::Binary:0x007f7f7ab53a78 @data="64d53e", @type=:generic>, #<BSON::Binary:0x007f7f7ab53960 @data="6ed747", @type=:generic>, #<BSON::Binary:0x007f7f7ab53870 @data="be81ff", @type=:generic>, #<BSON::Binary:0x007f7f7ab53730 @data="e950c4", @type=:generic>, #<BSON::Binary:0x007f7f7ab53618 @data="7da04e", @type=:generic>, #<BSON::Binary:0x007f7f7ab53190 @data="56fe72", @type=:generic>, #<BSON::Binary:0x007f7f7ab53050 @data="9a6cdf", @type=:generic>, #<BSON::Binary:0x007f7f7ab52f10 @data="96956e", @type=:generic>, #<BSON::Binary:0x007f7f7ab52e20 @data="c8e19d", @type=:generic>, #<BSON::Binary:0x007f7f7ab52c90 @data="7e7f2e", @type=:generic>, #<BSON::Binary:0x007f7f7ab527e0 @data="0b98dd", @type=:generic>, #<BSON::Binary:0x007f7f7ab526f0 @data="32c896", @type=:generic>, #<BSON::Binary:0x007f7f7ab52600 @data="5b0738", @type=:generic>, #<BSON::Binary:0x007f7f7ab524e8 @data="693c6d", @type=:generic>, #<BSON::Binary:0x007f7f7ab523d0 @data="4d2996", @type=:generic>]}} flags=[] limit=0 skip=0 batch_size=nil fields=nil runtime: 0.6100ms
      D, [2014-08-24T02:22:12.094905 #95340] DEBUG -- :   MOPED: 127.0.0.1:27017 QUERY        database=test collection=children selector={"$and"=>[{"_id"=>{"$in"=>[nil, nil, nil, nil, nil]}}]} flags=[] limit=0 skip=0 batch_size=nil fields=nil runtime: 0.3530ms
      []
      D, [2014-08-24T02:22:12.095608 #95340] DEBUG -- :   MOPED: 127.0.0.1:27017 QUERY        database=test collection=children selector={"$and"=>[{"_id"=>{"$in"=>[nil, nil, nil, nil, nil]}}]} flags=[] limit=0 skip=0 batch_size=nil fields=nil runtime: 0.3270ms
      []
      D, [2014-08-24T02:22:12.096201 #95340] DEBUG -- :   MOPED: 127.0.0.1:27017 QUERY        database=test collection=children selector={"$and"=>[{"_id"=>{"$in"=>[nil, nil, nil, nil, nil]}}]} flags=[] limit=0 skip=0 batch_size=nil fields=nil runtime: 0.2800ms
      []
      

            Assignee:
            Unassigned Unassigned
            Reporter:
            amw Adam Wróbel
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: