从MongoDB检索文档时不包括$ fields [英] Excluding $fields When Retrieving Document from MongoDB

查看:64
本文介绍了从MongoDB检索文档时不包括$ fields的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法可以从MongoDB中获取文档,而不是将某些字段转换为包含$个字段的对象?

Is there a way to get the document from MongoDB as is rather than having some fields converted to object containing $ fields?

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

For example, I have a field called timestamp where I store a long value. It used to return just a value and all the sudden it starts returning an object after about a week:

{
    "$numberLong": "1474402633708"
}

与嵌套对象的_id字段相同.它正在返回"_id",并在某个时候切换为返回一个带有$ oid的对象,例如顶层.我真的需要至少保持一致.

This is the same with _id field for a nested object. It was returning "_id" and at some point switched to return an object with $oid like for the top level. I really need it to at least be consistent.

这是MongoDB Client的屏幕截图.序列化为JSON时,第一个不会返回$ numberLong,而最后一个会返回$ numberLong.

Here's the screenshot from MongoDB Client. The first one when serialized to JSON doesn't return $numberLong while the last one does.

这只是某个地方的配置吗?绝对没有道理.

Is this just a configuration somewhere? It makes absolutely no sense.

这是从控制台中删除的,以免怀疑timestamp字段的数据不同.

And here's from the console to remove any doubt that the data for the timestamp field is different.

> 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对其进行测试.这是代码,以防万一.

I'm currently testing it with MongoDB Java lib v3.3.0. Here's the code just in case it helps.

//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,则可以替换它们.


Here's a workaround in Javascript to make sure data is consistent in case you run into this issue as well. This code uses some jQuery functions, but you can replace them if you don't use 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:


Update 1:

逐行调试后,我发现对于以某种方式将long value back解释为double(指数值)的情况,那么我得到了期望值,而那一则被解释为long(int64),我得到了由于默认模式为STRICT,因此我将获得$ numberLong.现在的问题是,长值在某些时候如何存储为double值,有时又存储为long的时间.

After debugging line-by-line, I found that for the case where long value back is somehow interpreted as double (exponential value), then I'm getting expected value back while the one interpreted as long (int64), I'm getting back $numberLong since the default mode is STRICT. Now the question is down to how did a long value sometime get stored as double and sometime as long.

推荐答案

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

I found the issue. It's the Mongo Client (http://www.mongoclient.com) that's saving the long value as double. The reason that my code suddenly break was because I was trying to remove corrupted data using the tool and the long value was then saved as double value. This caused it to become inconsistent. I didn't initially realize this since I didn't know that modifying one document actually causes every documents in the result sets to also be saved again or I would have figured this out much earlier.

并回答主题中的问题.您不能排除$ fields.序列化的工作方式如下:

And to answer the question in the subject. You can't exclude the $fields. The serialization works as follow:

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

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

There is no way to set the mode to null and get it to work since serialization of object ID will throw an exception for unknown mode.

这篇关于从MongoDB检索文档时不包括$ fields的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆