使用Mongo本机查询解析MongoDB DBRef数组并处理已解析的文档 [英] Resolving MongoDB DBRef array using Mongo Native Query and working on the resolved documents
问题描述
我的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
. DBRefs
是contain 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",因为没有诸如name
或area
之类的字段.
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屋!