Да, наистина, полето "territories"
има масив от препратки към бази данни
и not the actual documents
. DBRefs
са обекти, които contain information with which we can locate the actual documents
.
В горния пример можете ясно да видите това, задействайте следната mongo заявка:
db.maps.find({"_id":ObjectId("542489232436657966204394")}).forEach(function(do
c){print(doc.territories[0]);})
той ще отпечата обекта DBRef, а не самия документ:
o/p: DBRef("territories", ObjectId("5424892224366579662042e9"))
така че, '$sum': '$territories.name'
,'$sum': '$territories.area'
ще ви покаже '0', тъй като няма полета като name
или area
.
Така че трябва да разрешите тази препратка към документ, преди да направите нещо като $territories.name
За да постигнете това, което искате, можете да използвате map()
функция, тъй като агрегацията или Map-reduce поддържат подзаявки и вече имате самостоятелна map
документ с препратки към неговите 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:
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
в страната на сървъра. Вижте какво има да се каже в документацията:
Освен това, reduce
функция дори ако се използва (която така или иначе никога не може да работи) никога няма да бъде извикана за вашия проблем, тъй като група w.r.t "fileName"
или "ObjectId"
винаги ще има само един документ във вашия набор от данни.