1

I have in my mongo some documents which have doubles as one of their fields:

{ 
"_id" : "1b1a39a7-5a04-4a0c-9a9e-658b5c95b58d", 
"content" :
    {
        "NumTaux" : 0.00196713814946994, 
        "SourceYear" : NumberInt(2017), 
        "Year" : NumberInt(2020), 
        "Age" : NumberInt(-1), 
        "Sex" : "F"
    }
}

Studio 3T view

I use the mongo java driver to write to and read from our Mongo. When I am reading these documents, the doubles are sometimes converted to scientific notation:

enter image description here

I tried solving this by writing a custom codec for Doubles:

public class DoubleCodec implements Codec<Double> {
@Override
public Double decode(BsonReader reader, DecoderContext decoderContext) {
    return reader.readDouble();
}

@Override
public void encode(BsonWriter writer, Double value, EncoderContext encoderContext) {
    writer.writeDouble(value);
}

@Override
public Class<Double> getEncoderClass() {
    return Double.class;
}
}

and adding it to my collection's registry:

DoubleCodec doubleCodec = new DoubleCodec();
    CodecRegistry registry = CodecRegistries.fromRegistries(MongoClient.getDefaultCodecRegistry(),
                                                            CodecRegistries.fromCodecs(doubleCodec));
    matrixDataCollection = MongoFactory.obtainSyncClient(config)
                                       .getDatabase(config.getString(MONGO_DB))
                                       .getCollection(MATRIX_DATA_COLLECTION)
                                       .withCodecRegistry(registry);

But this doesn't seem to work, the decode method in the codec is never called as far as I can see (breakpoint/system out) My suspicion is that the already existing codec for Double is being called instead.

Is there any way to make it so that my own DoubleCodec gets called instead of the default one, or is there another way to configure how the default Double codec behaves?

Infiniteh
  • 634
  • 5
  • 8
  • isn't that just a output of `Double's toString()` method? – s7vr Aug 02 '17 at 17:58
  • Don't think so: The debugger shows a string representation , but you can always unfold the value field to see the actual value (for an actual string, it shows the underlying CharSequence for instance). When I look at the real values of the doubles in the Bson document it shows the raw values of some as 0.0019671381496994 and others as 5.58600702289802E-4 – Infiniteh Aug 03 '17 at 05:12

2 Answers2

0

The doubles are converted when you display them, not when they are read from the database.

In this case all you are seeing is what the debugger does at some undisclosed breakpoint which could be anywhere.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • The document in the debugging screenshot is the one that is returned by the mongo driver, so it does look to me like the conversion is happening there. This document also gets converted to a csv afterwards to return as part of an HTTP response. In the csv as well, it is stored as scientific notation. Thanks for your answer, but it doesn't matter where it is happening exactly, I don't want it to happen... – Infiniteh Aug 02 '17 at 16:51
0

It has nothing to do with the MongoDB driver or codecs. It's how double works in Java. The Double.toString() uses FloatingDecimal.toJavaFormatString(d) function under the hood which is an implementation of the IEEE-754 standard. So during the csv export you need to specify a format and convert the double, for example like this (from https://stackoverflow.com/a/25307973/7717350):

double val = 0.00005196713814946994d;

DecimalFormat df = new DecimalFormat("0");
df.setMaximumFractionDigits(340);

System.out.println(df.format(myValue)); //output: 0.00005196713814946994

You can find more infos on Double formatting here.

References:

mgyongyosi
  • 2,557
  • 2
  • 13
  • 20