Sim, o campo
"territories"
tem uma matriz de referências de banco de dados
e not the actual documents
. DBRefs
são objetos que contain information with which we can locate the actual documents
. No exemplo acima, você pode ver isso claramente, acione a consulta mongo abaixo:
db.maps.find({"_id":ObjectId("542489232436657966204394")}).forEach(function(do
c){print(doc.territories[0]);})
ele imprimirá o objeto DBRef em vez do próprio documento:
o/p: DBRef("territories", ObjectId("5424892224366579662042e9"))
então,
'$sum': '$territories.name'
,'$sum': '$territories.area'
mostraria '0' já que não há campos como name
ou area
. Então você precisa resolver essa referência a um documento antes de fazer algo como
$territories.name
Para conseguir o que deseja, você pode usar o
map()
função, uma vez que agregação nem Map-reduce suportam subconsultas, e você já tem um map
autocontido documento, com referências aos seus territories
. Passos para alcançar:
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.
Script de shell do 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
};
})
o/p:
[
{
"id" : "importFile1.json",
"noOfTerritories" : 2,
"areaSum" : 1906609
},
{
"id" : "importFile2.json",
"noOfTerritories" : 1,
"areaSum" : 0
}
]
Map-Reduce
funções não devem ser e não podem ser usadas para resolver DBRefs
no lado do servidor. Veja o que a documentação tem a dizer:Além disso, um
reduce
função mesmo se usada (que nunca pode funcionar de qualquer maneira) nunca será chamada para o seu problema, pois um grupo w.r.t "fileName"
ou "ObjectId"
sempre teria apenas um documento, em seu conjunto de dados.