MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Resolvendo o array MongoDB DBRef usando o Mongo Native Query e trabalhando nos documentos resolvidos


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.