@@ -919,6 +919,54 @@ BSONObj normalizeNumerics(const BSONObj& input) {
919
919
return bob.obj ();
920
920
}
921
921
922
+ void roundFloatingPointNumericElementsHelper (const BSONObj& input, BSONObjBuilder& bob);
923
+
924
+ void roundFloatingPointNumericElements (const BSONElement& el, BSONObjBuilder& bob) {
925
+ switch (el.type ()) {
926
+ case NumberDouble: {
927
+ // Take advantage of Decimal128's ability to round to 15 digits at construction time.
928
+ bob.append (el.fieldName (),
929
+ Decimal128 (el.numberDouble (), Decimal128::kRoundTo15Digits ).toDouble ());
930
+ break ;
931
+ }
932
+ case Array: {
933
+ BSONObjBuilder sub (bob.subarrayStart (el.fieldNameStringData ()));
934
+ for (const auto & child : el.Array ()) {
935
+ roundFloatingPointNumericElements (child, sub);
936
+ }
937
+ sub.doneFast ();
938
+ break ;
939
+ }
940
+ case Object: {
941
+ BSONObjBuilder sub (bob.subobjStart (el.fieldNameStringData ()));
942
+ roundFloatingPointNumericElementsHelper (el.Obj (), sub);
943
+ sub.doneFast ();
944
+ break ;
945
+ }
946
+ default :
947
+ bob.append (el);
948
+ break ;
949
+ }
950
+ }
951
+
952
+ void roundFloatingPointNumericElementsHelper (const BSONObj& input, BSONObjBuilder& bob) {
953
+ BSONObjIterator it (input);
954
+ while (it.more ()) {
955
+ roundFloatingPointNumericElements (it.next (), bob);
956
+ }
957
+ }
958
+
959
+ /* *
960
+ * Returns a new BSONObj with the same field/value pairings, but with floating-point types rounded
961
+ * to 15 digits of precision. For example, 1.000000000000001 and NumberDecimal('1') would
962
+ * be normalized into the same number.
963
+ */
964
+ BSONObj roundFloatingPointNumerics (const BSONObj& input) {
965
+ BSONObjBuilder bob (input.objsize ());
966
+ roundFloatingPointNumericElementsHelper (input, bob);
967
+ return bob.obj ();
968
+ }
969
+
922
970
void removeNullAndUndefinedElementsHelper (const BSONObj& input, BSONObjBuilder& bob);
923
971
924
972
template <typename Builder>
@@ -986,6 +1034,9 @@ BSONObj normalizeBSONObj(const BSONObj& input, NormalizationOptsSet opts) {
986
1034
if (isSet (opts, NormalizationOpts::kConflateNullAndMissing )) {
987
1035
result = removeNullAndUndefined (result);
988
1036
}
1037
+ if (isSet (opts, NormalizationOpts::kRoundFloatingPointNumerics )) {
1038
+ result = roundFloatingPointNumerics (result);
1039
+ }
989
1040
if (isSet (opts, NormalizationOpts::kNormalizeNumerics )) {
990
1041
result = normalizeNumerics (result);
991
1042
}
0 commit comments