MongoDB Java driver: Undefined values are not shown

大憨熊 提交于 2019-12-25 07:10:06

问题


Open mongo shell and create a document with a undefined value:

> mongo
MongoDB shell version: 2.4.0
connecting to: test
> use mydb
switched to db mydb
> db.mycol.insert( {a_number:1, a_string:"hi world", a_null:null, an_undefined:undefined} );
> db.mycol.findOne();
{
        "_id" : ObjectId("51c2f28a7aa5079cf24e3999"),
        "a_number" : 1,
        "a_string" : "hi world",
        "a_null" : null,
        "an_undefined" : null
}

As we can see, javascript translates the "undefined" value (stored in the db) to a "null" value, when showing it to the user. But, in the db, the value is still "undefined", as we are going to see with java.

Let's create a "bug_undefined_java_mongo.java" file, with the following content:

import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.MongoClient;


public class bug_undefined_java_mongo
{

    String serv_n = "myserver";     // server name
    String db_n   = "mydb";         // database name
    String col_n  = "mycol";        // collection name


    public static void main(String[] args)
    {        
        new bug_undefined_java_mongo().start();        
    }


    public void start()
    {

        pr("Connecting to server ...");      
        MongoClient cli = null;
        try
        {
            cli = new MongoClient( serv_n );           
        }
        catch (Exception e)
        {
            pr("Can't connecto to server: " + e);
            System.exit(1);
        }
        if (cli == null)
        {
            pr("Can't connect to server");
            System.exit(1);
        }


        pr("Selecting db ...");
        DB db_res = cli.getDB( db_n );


        pr("Selecting collection ...");      
        DBCollection col = db_res.getCollection( col_n );


        pr("Searching documents ...");
        DBCursor cursor = null;
        try
        {
            cursor = col.find( );
        }
        catch (Exception e)
        {
            pr("Can't search for documents: " + e);
            System.exit(1);
        }


        pr("Printing documents ...");
        try
        {
            while (cursor.hasNext())
            {
                Object doc_obj = cursor.next();                
                System.out.println("doc: " + doc_obj);
            }
        }
        catch (Exception e)
        {
            pr("Can't browse documents: " + e);
            return;
        }
        finally
        {
            pr("Closing cursor ...");
            cursor.close();
        }

    }


    public void pr(String cad)
    {
        System.out.println(cad);
    }    

}

After compiling and running it, we get this:

Connecting to server ...
Selecting db ...
Selecting collection ...
Searching documents ...
Printing documents ...
doc: { "_id" : { "$oid" : "51c2f0f85353d3425fcb5a14"} , "a_number" : 1.0 , "a_string" : "hi world" , "a_null" :  null }
Closing cursor ...

We see that the "a_null:null" pair is shown, but... the "an_undefined:undefined" pair has disappeared! (both the key and the value).

Why? Is it a bug?

Thank you


回答1:


Currently undefined is not supported by the java driver as there is no equivalent mapping in java.

Other drivers such as pymongo and the js shell handles this differently by casting undefined to None when representing the data, however it is a separate datatype and is deprecated in the bson spec.

If you need it in the java driver then you will have to code your own decoder factory and then set it like so:

collection.setDBDecoderFactory(MyDecoder.FACTORY);

A minimal example that has defined handling for undefined and factory is available on github in the horn of mongo repo.




回答2:


I see, creating a factory could be a solution.

Anyway, probably many developers would find it useful the posibility of enabling a mapping in the driver to convert automatically "undefined" values to "null" value. For example, by calling a mapUndefToNull() method:

cli = new MongoClient( myserver );
cli.mapUndefToNull(true);

In my case, I'm running a MapReduce (it is Javascript code) on my collections, and I am having to explicitly convert the undefined values (generated when accessing to non existent keys) to null, in order to avoid Java driver to remove it:

try { value = this[ key ] }  catch(e) {value = null}
if (typeof value == "undefined")  value = null;      // avoid Java driver to remove it

So, as a suggestion, I'd like the mapUndefToNull() method to be added to the Java driver. If possible.

Thank you



来源:https://stackoverflow.com/questions/17213965/mongodb-java-driver-undefined-values-are-not-shown

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!