Reputation: 241
The number is larger than 9223372036854775807 - too big for NumberLong, which is mongo's native 64-bit long type. What's the best way to do this/the best field type?
Is it possible to preserve any of the querying functionality of a smaller integer (such as {$lt}
)?
The big numbers are being generated by bignumber.js, and I'm using mongoose to interact with mongoDb.
Upvotes: 7
Views: 7268
Reputation: 23041
Since MongoDB 3.4, it is possible to use NumberDecimal
type (also documented as Decimal128
on MongoDB & Mongoose docs) following the IEEE 754 spec.
It has the ability to store maximum and minimum values in the order of 10^6144 and 10^-6143, and supports 34 decimal digits of precision (source).
Tested with Mongoose 6.6:
const mongoose = require('mongoose');
const StatisticsSchema = mongoose.Schema({
someMetric: { type: mongoose.Types.Decimal128, default: 0 },
...
}
Storing a Decimal128 value in DB requires doing:
statistic.someMetric = new mongoose.Types.Decimal128(someNumber.toString());
await statistic.save();
It supports all the MongoDB operators I could test so far ($gt
, $lt
...) and even aggregation pipelines with operators like $sum
.
On the NodeJS side, to overcome Number
type limitations (safe integers up to 2^53-1, i.e. ~9 quadrillions), you can use builtin BigInt
if you don't need decimals. Overall, the conversions between BigInt
(JS side) & Decimal128
(Mongo side) can be cumbersome (e.g. you may have to remove trailing ".0000" from Decimal128
numbers retrieved from DB), however such an approach was definitely a viable option for my use case.
Upvotes: 0
Reputation: 28621
I'm afraid that the only viable/safe option would be to store such big numbers as a string
and serialize it back and forth between the application and MongoDB when read/written. However, you will loose the ability to use MongoDB built-in functions that work with numbers (you can still cast the values to numbers, but it won't be safe anymore).
Upvotes: 1