2016-09-20 34 views
0

有沒有辦法從MongoDB中直接獲取文檔,而不是將某些字段轉換爲包含$字段的對象?

例如,我有一個名爲timestamp的字段,用於存儲長整型值。它曾經只返回一個值和所有它開始大約一個星期後,返回一個對象突然:

{ 
    "$numberLong": "1474402633708" 
} 

這是與嵌套對象_id字段相同。它返回「_id」,並在某個時刻切換到返回帶有$ oid的對象,如頂層。我真的需要它至少保持一致。

下面是MongoDB客戶端的截圖。序列化爲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:

調試行由行之後,我發現,其中長值回以某種方式解釋爲雙(指數值)的話,那麼我越來越期望值返回,而解釋爲long(int64),因爲默認模式爲STRICT,所以我回到了$ numberLong。現在的問題是,如何將長時間的價值存儲爲雙倍和長期存儲。

+0

它發生在您的應用程序內使用驅動程序,或在Mongo殼? –

+0

使用MongoDB Java客戶端時發生這種情況。 – juminoz

+0

更具體地說,我在toJson方法調用的返回值中看到了這一點。 – juminoz

回答

0

我發現了這個問題。這是Mongo Client(http://www.mongoclient.com),它將長期價值保存爲雙倍。我的代碼突然中斷的原因是因爲我試圖使用該工具刪除損壞的數據,然後將長整型值保存爲double值。這導致它變得不一致。我最初沒有意識到這一點,因爲我不知道修改一個文檔實際上會導致結果集中的每個文檔都被再次保存,或者我早就想到了這一點。

並回答主題中的問題。您不能排除$字段。序列化工作如下:

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

有沒有辦法將模式設置爲null,獲得自對象ID的序列化它的工作將拋出未知模式異常。

0

您使用哪個客戶端訪問您的mongoDB?

好像你的客戶端顯示的數據格式錯誤。如果你更喜歡gui客戶端,你可以用mongo shell或robomongo來檢查。

+0

數據至少在時間戳字段中沒有被正確顯示。你可以看到上面的mongo shell輸出。他們完全一樣。這是除非你說mongo shell也是不正確的。 – juminoz

+0

外殼沒有錯誤。但是我親身體驗過的mongo shell和java驅動之間存在一些差距。 –

+0

我添加了對問題的更新。沒有$ numberLong的情況下序列化的那個以某種方式存儲爲double。 – juminoz