-
Type: New Feature
-
Resolution: Won't Do
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Attributes
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"}
- is related to
-
MONGOID-5631 Resolve Mongoid compatibility issues with bson-ruby deserializing decimal128 to BigDecimal
- Closed