使用Mongo本机查询解析MongoDB DBRef数组并处理已解析的文档 [英] Resolving MongoDB DBRef array using Mongo Native Query and working on the resolved documents

查看:278
本文介绍了使用Mongo本机查询解析MongoDB DBRef数组并处理已解析的文档的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的MongoDB集合由2个主要集合组成:

My MongoDB collection is made up of 2 main collections :

1)地图

{
"_id" : ObjectId("542489232436657966204394"),
"fileName" : "importFile1.json",
"territories" : [ 
    {
        "$ref" : "territories",
        "$id" : ObjectId("5424892224366579662042e9")
    }, 
    {
        "$ref" : "territories",
        "$id" : ObjectId("5424892224366579662042ea")
    }
]
},

{
    "_id" : ObjectId("542489262436657966204398"),
    "fileName" : "importFile2.json",
    "territories" : [ 
        {
            "$ref" : "territories",
            "$id" : ObjectId("542489232436657966204395")
        }
    ],
    "uploadDate" : ISODate("2012-08-22T09:06:40.000Z")
}

2)在地图"对象中引用的地区:

2) Territories, which are referenced in "Map" objects :

{
    "_id" : ObjectId("5424892224366579662042e9"),
    "name" : "Afghanistan",
    "area" : 653958
},
{
    "_id" : ObjectId("5424892224366579662042ea"),
    "name" : "Angola",
    "area" : 1252651
},
{
    "_id" : ObjectId("542489232436657966204395"),
    "name" : "Unknown",
    "area" : 0
}

我的目标是列出每张地图及其累积面积和领土数量.我正在尝试以下查询:

My objective is to list every map with their cumulative area and number of territories. I am trying the following query :

db.maps.aggregate(
    {'$unwind':'$territories'},
    {'$group':{
        '_id':'$fileName',
        'numberOf': {'$sum': '$territories.name'}, 
        'locatedArea':{'$sum':'$territories.area'}
        }
    })

但是,对于每个值,结果显示为0:

However the results show 0 for each of these values :

{
    "result" : [ 
        {
            "_id" : "importFile2.json",
            "numberOf" : 0,
            "locatedArea" : 0
        }, 
        {
            "_id" : "importFile1.json",
            "numberOf" : 0,
            "locatedArea" : 0
        }
    ],
    "ok" : 1
}

尝试访问Territory的成员变量(名称和区域)时,我可能做错了,但是在Mongo文档中找不到这种情况的示例.区域存储为整数,名称存储为字符串.

I probably did something wrong when trying to access to the member variables of Territory (name and area), but I couldn't find an example of such a case in the Mongo doc. area is stored as an integer, and name as a string.

推荐答案

尝试访问Territory的成员变量(名称和区域)时,我可能做错了,但找不到示例 Mongo文档中的这种情况.区域存储为整数,并且 名称为字符串.

I probably did something wrong when trying to access to the member variables of Territory (name and area), but I couldn't find an example of such a case in the Mongo doc. area is stored as an integer, and name as a string.

确实,字段"territories"具有一个数据库引用not the actual documents. DBRefscontain information with which we can locate the actual documents的对象.

Yes indeed, the field "territories" has an array of database references and not the actual documents. DBRefs are objects that contain information with which we can locate the actual documents.

在上面的示例中,您可以清楚地看到这一点,并触发以下mongo查询:

In the above example, you can clearly see this, fire the below mongo query:

db.maps.find({"_id":ObjectId("542489232436657966204394")}).forEach(function(do
c){print(doc.territories[0]);})

它将打印DBRef对象而不是文档本身:

it will print the DBRef object rather than the document itself:

o/p: DBRef("territories", ObjectId("5424892224366579662042e9"))

因此,'$sum': '$territories.name''$sum': '$territories.area'会显示"0",因为没有诸如namearea之类的字段.

so, '$sum': '$territories.name','$sum': '$territories.area' would show you '0' since there are no fields such as name or area.

因此,在执行$territories.name

要实现所需的功能,可以使用map()函数,因为聚合和Map-reduce支持子查询,并且您已经有一个独立的map文档,其中引用了它的territories

To achieve what you want, you can make use of the map() function, since aggregation nor Map-reduce support sub queries, and you already have a self-contained map document, with references to its territories.

实现步骤:

a) get each map
b) resolve the `DBRef`.
c) calculate the total area, and the number of territories.
d) make and return the desired structure.

Mongo shell脚本:

Mongo shell script:

db.maps.find().map(function(doc) {
    var territory_refs = doc.territories.map(function(terr_ref) {
        refName = terr_ref.$ref;
        return terr_ref.$id;
    });
    var areaSum = 0;
    db.refName.find({
        "_id" : {
            $in : territory_refs
        }
    }).forEach(function(i) {
        areaSum += i.area;
    });
    return {
        "id" : doc.fileName,
        "noOfTerritories" : territory_refs.length,
        "areaSum" : areaSum
    };
})

o/p:

[
        {
                "id" : "importFile1.json",
                "noOfTerritories" : 2,
                "areaSum" : 1906609
        },
        {
                "id" : "importFile2.json",
                "noOfTerritories" : 1,
                "areaSum" : 0
        }
]

Map-Reduce函数不应且不能用于在服务器端解析DBRefs. 看看文档怎么说:

Map-Reduce functions should not be and cannot be used to resolve DBRefs in the server side. See what the documentation has to say:

由于任何原因,地图功能均不应访问数据库.

The map function should not access the database for any reason.

map函数应该是纯函数,否则对外部函数没有任何影响 功能(即副作用)

The map function should be pure, or have no impact outside of the function (i.e. side effects.)

reduce函数不应访问数据库,即使执行 读取操作.减少功能不应影响外部 系统.

The reduce function should not access the database, even to perform read operations. The reduce function should not affect the outside system.

此外,即使使用了reduce函数(无论如何也永远无法工作),也永远不会因您的问题而调用它,因为wrt "fileName""ObjectId"组在您的数据集中将始终只有一个文档.

Moreover, a reduce function even if used(which can never work anyway) will never be called for your problem, since a group w.r.t "fileName" or "ObjectId" would always have only one document, in your dataset.

MongoDB不会为只有一个键的键调用reduce函数 单一值

MongoDB will not call the reduce function for a key that has only a single value

这篇关于使用Mongo本机查询解析MongoDB DBRef数组并处理已解析的文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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