How to aggregate fields from embedded documents in Mongoose

匿名 (未验证) 提交于 2019-12-03 09:06:55

问题:

Coverage Model.

var CoverageSchema = new Schema({ module : String, source: String, namespaces: [{         name: String,         types: [{                 name: String,                  functions: [{                         name: String,                          coveredBlocks: Number,                         notCoveredBlocks: Number                     }]             }]     }] }); 

I need coveredBlocks aggregations on every level:

*Module: {moduleBlocksCovered}, // SUM(blocksCovered) GROUP BY module, source **Namespaces: [{nsBlocksCovered}] // SUM(blocksCovered) GROUP BY module, source, ns ****Types: [{typeBlocksCovered}] // SUM(blocksCovered) BY module, source, ns, type 

How do I get this result with Coverage.aggregate in Mongoose ?

{ module: 'module1', source: 'source1', coveredBlocks: 7, // SUM of all functions in module namespaces:[      name: 'ns1',      nsBlocksCovered: 7, // SUM of all functions in namespace      types:[      {          name: 'type1',          typeBlocksCovered: 7, // SUM(3, 4) of all function in type          functions[          {name: 'func1', blocksCovered: 3},          {name:'func2', blocksCovered: 4}]      }      ] ] } 

回答1:

My ideas is to deconstruct everything using $unwind then reconstruct the document back again using group and projection.

aggregate flow:  //deconstruct functions unwind(namesapces)  unwind(namespaces.types) unwind(namespace.types.functions) //cal typeBlocksCovered group module&source ,ns,type to sum functions blocksCovered->typeBlocksCovered + push functions back to types project to transform fields to be easier for next group // cal nsBlocksCovered group module&source ,ns to sum typeBlocksCovered -> nsBlocksCovered) + push types back to ns project to transform fields to be easier for next group // cal coveredBlocks group module&source to sum nsBlocksCovered  -> coveredBlocks project to transform fields to match your mongoose docs 

My sample query with mongo shell syntax and its seem working , guess is you are using collection name "Coverage"

db.Coverage.aggregate([     {"$unwind":("$namespaces")}     ,{"$unwind":("$namespaces.types")}     ,{"$unwind":("$namespaces.types.functions")}     ,{"$group": {         _id: {module:"$module", source:"$source", nsName: "$namespaces.name", typeName : "$namespaces.types.name"}         , typeBlocksCovered : { $sum : "$namespaces.types.functions.blocksCovered"}         , functions:{ "$push": "$namespaces.types.functions"}}}      ,{"$project" :{module:"$_id.module", source:"$_id.source"                     ,namespaces:{                          name:"$_id.nsName"                         ,types : { name: "$_id.typeName",typeBlocksCovered : "$typeBlocksCovered" ,functions: "$functions"}                     }                     ,_id:0}}       ,{"$group": {         _id: {module:"$module", source:"$source", nsName: "$namespaces.name"}         , nsBlocksCovered : { $sum : "$namespaces.types.typeBlocksCovered"}         , types:{ "$push": "$namespaces.types"}}}     ,{"$project" :{module:"$_id.module", source:"$_id.source"                     ,namespaces:{                          name:"$_id.nsName"                         ,nsBlocksCovered:"$nsBlocksCovered"                         ,types : "$types"                     }                     ,_id:0}}     ,{"$group": {         _id: {module:"$module", source:"$source"}         , coveredBlocks : { $sum : "$namespaces.nsBlocksCovered"}         , namespaces:{ "$push": "$namespaces"}}}     ,{"$project" :{module:"$_id.module", source:"$_id.source", coveredBlocks : "$coveredBlocks", namespaces: "$namespaces",_id:0}}        ]) 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!