0

mongo シェルを開き、値が未定義のドキュメントを作成します。

> 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
}

ご覧のとおり、javascript は、ユーザーに表示するときに、「未定義」の値 (データベースに格納されている) を「null」の値に変換します。しかし、データベースでは、値はまだ「未定義」です。これは、Java で確認できます。

次の内容の「bug_undefined_java_mongo.java」ファイルを作成しましょう。

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);
    }    

}

コンパイルして実行すると、次のようになります。

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 ...

「a_null:null」のペアが表示されているのがわかりますが、「an_undefined:undefined」のペアは消えています。(キーと値の両方)。

なんで?バグですか?

ありがとうございました

4

2 に答える 2

2

Java には同等のマッピングがないため、現在undefinedJava ドライバではサポートされていません。

pymongo や js シェルなどの他のドライバーは、データを表すときに にキャストundefinedすることでこれを別の方法で処理Noneしますが、これは別のデータ型であり、bson 仕様では非推奨です。

Java ドライバーで必要な場合は、独自のデコーダー ファクトリをコーディングし、次のように設定する必要があります。

collection.setDBDecoderFactory(MyDecoder.FACTORY);

およびファクトリの処理を定義した最小限の例は、mongoundefinedリポジトリの角にある github で入手できます。

于 2013-06-24T15:05:11.387 に答える
0

なるほど、工場を作ることが解決策になるかもしれません。

とにかく、おそらく多くの開発者は、ドライバーのマッピングを有効にして「未定義」値を「null」値に自動的に変換できると便利だと思うでしょう。たとえば、mapUndefToNull() メソッドを呼び出すと、次のようになります。

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

私の場合、コレクションで MapReduce (Javascript コード) を実行しており、Java ドライバーが削除されないようにするために、未定義の値 (存在しないキーにアクセスするときに生成される) を明示的に null に変換する必要があります。それ:

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

そこで、提案として、mapUndefToNull() メソッドを Java ドライバーに追加してほしいと思います。もし可能なら。

ありがとうございました

于 2013-06-25T07:53:14.540 に答える