从MongoDB中检索文档时排除$字段

时间:2016-09-20 20:28:05

标签: java mongodb object numbers

有没有办法从MongoDB中获取文件,而不是将某些字段转换为包含$ fields的对象?

例如,我有一个名为timestamp的字段,我存储一个long值。它过去只返回一个值,突然它在大约一周后开始返回一个对象:

{
    "$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:

在逐行调试之后,我发现对于长值返回以某种方式被解释为double(指数值)的情况,然后我得到期望值,而解释为long(int64),I因为默认模式是STRICT,所以要回$ numberLong。现在的问题是,某个时间段的长值如何被存储为double,有时甚至长。

2 个答案:

答案 0 :(得分:0)

您使用哪个客户端访问mongoDB?

好像您的客户端正在以错误的格式显示数据。如果您更喜欢gui客户端,可以使用mongo shell或robomongo进行检查。

答案 1 :(得分:0)

我发现了这个问题。 Mongo客户端(http://www.mongoclient.com)将long值保存为double。我的代码突然中断的原因是因为我试图使用该工具删除损坏的数据,然后将long值保存为double值。这导致它变得不一致。我最初没有意识到这一点,因为我不知道修改一个文档实际上会导致结果集中的每个文档也被再次保存,或者我会更早地解决这个问题。

并回答主题中的问题。您不能排除$字段。序列化的工作原理如下:

{
  "properties": {
    "dateOfBirth": {
      "null_value": "1970-01-01T00:00:00Z",
      "type": "date"
    }
  }
}

无法将模式设置为null并使其工作,因为对象ID的序列化将为未知模式抛出异常。