Tak, rzeczywiście, pole "territories"
ma tablicę odniesienia do baz danych
i not the actual documents
. DBRefs
są obiektami, które contain information with which we can locate the actual documents
.
W powyższym przykładzie możesz to wyraźnie zobaczyć, uruchom poniższe zapytanie mongo:
db.maps.find({"_id":ObjectId("542489232436657966204394")}).forEach(function(do
c){print(doc.territories[0]);})
wydrukuje obiekt DBRef, a nie sam dokument:
o/p: DBRef("territories", ObjectId("5424892224366579662042e9"))
więc '$sum': '$territories.name'
,'$sum': '$territories.area'
pokaże ci „0”, ponieważ nie ma pól, takich jak name
lub area
.
Musisz więc rozwiązać to odniesienie do dokumentu, zanim zrobisz coś takiego jak $territories.name
Aby osiągnąć to, czego chcesz, możesz skorzystać z map()
funkcja, ponieważ agregacja lub Map-reduce obsługują podzapytania, a Ty masz już samodzielną map
dokument, z odniesieniami do jego territories
.
Kroki do osiągnięcia:
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.
Skrypt powłoki Mongo:
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
};
})
w/w:
[
{
"id" : "importFile1.json",
"noOfTerritories" : 2,
"areaSum" : 1906609
},
{
"id" : "importFile2.json",
"noOfTerritories" : 1,
"areaSum" : 0
}
]
Map-Reduce
funkcje nie powinny być i nie mogą być używane do rozwiązywania DBRefs
po stronie serwera. Zobacz, co dokumentacja ma do powiedzenia:
Co więcej, reduce
funkcja, nawet jeśli jest używana (która i tak nigdy nie zadziała), nigdy nie zostanie wywołana dla twojego problemu, ponieważ grupa w.r.t "fileName"
lub "ObjectId"
zawsze miałby tylko jeden dokument w Twoim zbiorze danych.