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

Force int64 storage via BSON::Int64 field type

    • Type: Icon: New Feature New Feature
    • Resolution: Won't Do
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: None
    • Component/s: Attributes
    • Labels:

      MongoDB server provides two integer types: int32 and int64. In Ruby there is only one integer type called Integer which can store arbitrarily large values; normally, when an integer value is written to MongoDB, the driver serializes Ruby integers into the smallest of the BSON integer types that is big enough.

      Sometimes applications wish to force the use of BSON 64-bit integers for a particular value even if it would fit into a 32-bit integer, presumably for compatibility with other applications.

      The driver appears to permit this via explicitly inserting values of BSON::Int64, but Mongoid appears to have no equivalent handling and when a user declares a field of BSON::Int64 type the values can be inserted as 32-bit integers anyway.

      When a document field is declared to be of BSON::Int64 type, integers written to that field should be stored as 64-bit integers.
      When a document field declared to be of Object type is assigned a BSON::Int64 value, the value should be stored in MongoDB as an int64.

      BSON::Int64 field in Mongoid should generally behave as an Integer field, specifically when:
      A floating-point value is written into it
      An integer out of int64 range is written into it
      A string with a numeric value is written into it
      A string with a non-numeric value is written into it

      An interesting point to consider is what types of values a BSON::Int64 field returns. Returning actual BSON::Int64 instances might be too awkward to work with, therefore I think there needs to be either 1) a bit in our documentation telling users how to define a type which stores int64 but returns values as Ruby integers or 2) actually making that type in addition to or instead of a type that returns the values as BSON::Int64 instances.


      Mongoid will store integer values in the range of (-2**64..2**64-1).include?(value) && !(-2**32..2**32-1).include?(value) as Int32 even if a type of BSON::Int64 is explicitly set, as opposed to the driver which will store the value as the requested type.

      # Driver
      
      client = Mongo::Client.new('mongodb://...')
      collection = client[:foo]
      collection.drop
      collection.insert_one bar: BSON::Int64.new(1)
      puts collection.aggregate([{ '$project' => { 'bar': 1, 'type': { '$type' => '$bar' } } }]).to_a
      
      # => {"_id"=>BSON::ObjectId('605b4100ceb023f7f59308e5'), "bar"=>1, "type"=>"long"}
      
      # Mongoid
      
      class Foo
        include Mongoid::Document
        field :bar, type: BSON::Int64
      end
      
      Mongoid.configure { |config|  config.clients.default = {  uri: "mongodb://..." } }
      Foo.collection.drop
      Foo.create(bar: 1)
      puts Foo.collection.aggregate([{ '$project' => { 'bar': 1, 'type': { '$type' => '$bar' } } }]).to_a
      
      # => {"_id"=>BSON::ObjectId('605b3733ceb023d2e722b8f5'), "bar"=>1, "type"=>"int"}
      

            Assignee:
            neil.shweky@mongodb.com Neil Shweky (Inactive)
            Reporter:
            alex.bevilacqua@mongodb.com Alex Bevilacqua
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: