2016-09-20 1 views
0

$フィールドを含むオブジェクトに変換されたフィールドを持つのではなく、MongoDBからドキュメントを取得する方法はありますか?

たとえば、私は長い値を格納するタイムスタンプというフィールドを持っています。

{ 
    "$numberLong": "1474402633708" 
} 

これは、ネストされたオブジェクトの_idフィールドと同じである:それはちょうど値と、それはおよそ一週間後のオブジェクトを返す開始し、すべての突然のを返すために使用されます。それは "_id"を返していて、ある時点でトップレベルのように$ oidのオブジェクトを返すように切り替えました。私は少なくともそれが一貫していることが本当に必要です。

ここにMongoDB Clientのスクリーンショットがあります。 JSONにシリアル化されたときの最初のものは、最後のものが$ numberLongを返しません。

enter image description here

どこかだけの構成このですか?それは絶対に意味をなさない。

ここからコンソールから、タイムスタンプフィールドのデータが異なることを疑いなく削除します。

> db["page"].find() 
{ "_id" : ObjectId("57dd99ab390a777a9720e8c2"), "entries" : [ { "widget" : { "_id" : ObjectId("57dec085390a777a9720e8c5"), "_db" : "system-s", "_col" : "card" }, "width" : -1, "height" : -1 }, { "widget" : { "_id" : ObjectId("57df6119390a778641f4fd25"), "_db" : "system-s", "_col" : "card" }, "width" : -1, "height" : -1 } ], "title" : "Simple 2", "timestamp" : 1474257177398 } 
{ "_id" : ObjectId("57e171ff303c2807d6ea1dd6"), "entries" : [ { "widget" : { "_id" : ObjectId("57e1720b303c2807d6ea1dd9"), "_db" : "system-s", "_col" : "card" }, "width" : -1, "height" : -1 } ], "title" : "Test 2", "timestamp" : 1474392587984 } 

現在、MongoDB Java lib v3.3.0でテストしています。ちょうどそれが役に立つ場合のためのコードはここにあります。

//the endpoint is exposed using Spark 
get("/db/:collection/get/:id", (request, response) -> { 
    String collectionName = request.params(":collection"); 
    String id = request.params(":id"); 

    Document doc = getDocument(collectionName, id); 
    return doc.toJson(); //this is where I see the issues 
}); 

public Document getDocument(String collectionName, String id){ 
    MongoCollection<Document> coll = db.getCollection(collectionName); 

    BasicDBObject query = new BasicDBObject(); 
    query.put("_id", new ObjectId(id)); 
    FindIterable<Document> itr = coll.find(query); 
    Document doc = itr.first(); 
    if(doc != null){ 
     return doc; 
    } 

    return null; 
} 

ここでのデータはあなたにも、この問題に遭遇した場合に一貫性があることを確認するにはJavaScriptでの回避策です。このコードではjQuery関数をいくつか使用していますが、jQueryを使用しない場合はそれらを置き換えることができます。

function scrub(obj){ 
    if(obj.$oid){ 
     return obj.$oid; 
    }else if(obj.$numberLong){ 
     return parseInt(obj.$numberLong); 
    }else if(obj.$numberInt){ 
     return parseInt(obj.$numberInt); 
    }else if(obj.$date){ 
     if($.isPlainObject(obj.$date) && obj.$date.$numberLong){ 
      return parseInt(obj.$date.$numberLong); 
     }else{ 
      return parseInt(obj.$date); 
     } 
    }else{ 
     $.each(obj, function(k, v){ 
      if($.isPlainObject(v)){ 
       obj[k] = scrub(v); 
      }else if($.isArray(v)){ 
       $.each(v, function(kk, vv){ 
        if($.isPlainObject(vv)){ 
         v[kk] = scrub(vv); 
        } 
       }); 
      } 
     }); 
    } 

    return obj; 
}; 

アップデート1:

ライン・バイ・ラインをデバッグした後、私は戻って長い値は何とか二重(指数値)として解釈される場合のために、私は取得していますことを発見しました期待値が返ってきている間にint(int64)と解釈され、デフォルトモードがSTRICTなので$ numberLongに戻ります。さて、長い値がいつ二倍に記憶されるのか、時にはそれと同じくらい長く保管されるのかという疑問があります。

+0

ドライバを使用して、またはMongoシェルでアプリケーション内部で発生しますか? –

+0

これは、MongoDB Javaクライアントを使用しているときに起こります。 – juminoz

+0

具体的には、toJsonメソッド呼び出しの戻り値でこれを確認します。 – juminoz

答えて

0

問題が見つかりました。 long値をdoubleとして保存するのはMongoクライアント(http://www.mongoclient.com)です。私のコードが突然破損した理由は、ツールを使用して破損したデータを削除しようとしていたため、long値がdouble値として保存されたためです。これは、それが矛盾するようになった。ある文書を修正すると、実際に結果セットのすべての文書が再び保存されるということを知らなかったので、最初はこれを認識しませんでした。あるいは、これをもっと早く見つけたでしょう。

そして、この問題の質問に答えてください。 $フィールドは除外できません。シリアライズは、次のように動作します:

32 int -> always value 
64 int -> STRICT uses $numberLong, CONSOLE uses NumberLong(d), UNKNOWN uses value 
double -> always value 

オブジェクトIDのシリアル化が未知のモードの例外がスローされますので、ヌル、それが仕事を得るためにモードを設定する方法はありません。

0

mongoDBにアクセスするクライアントはどれですか?

クライアントのデータが間違った形式で表示されているようです。あなたはGUIクライアントを好む場合はmongoシェルまたはrobomongoでこれを確認することができます。

+0

少なくともタイムスタンプフィールドのデータが正しく表示されていません。上記のmongoシェルの出力を見ることができます。彼らはまったく同じです。これは、mongo shellも間違っていると言っていない限りです。 – juminoz

+0

シェルが正しくありません。しかし、私が個人的に経験したmongo shellとjavaドライバの間にはいくつかのギャップがあります。 –

+0

質問に更新を加えました。 $ numberLongなしで長い間シリアライズされたものは何とかdoubleとして格納されます。 – juminoz

関連する問題