猫鼬聚合子文档的属性并显示结果

时间:2020-02-06 14:01:10

标签: mongodb

我有一个带有子文档的文档(未引用 )。我想将汇总应用于子文档的字段。

架构

const MFileSchema = new Schema({
  path: String,
  malwareNames: [String],
  title: String,
  severity: String // i want to aggregate bases on this field
});

const ScanSchema = new Schema({
  agent: { type: Schema.Types.ObjectId, ref: "Agent" },
  completedAt: Date,
  startedAt: { type: Date, default: Date.now() },
  mFiles: [MFileSchema] // array of malicious files schema
});

模型

let Scan = model("Scan", ScanSchema);

任务

Find the sum of severity in all scan documents of particular agents.

// agents is an array Agents (the schema is not important to show, consider the _id)

我正在使用的汇总查询

let c = await Scan.aggregate([
        { $match: { agent: agents } },
        { $project: { "mFiles.severity": true } },
        { $group: { _id: "$mFiles.severity", count: { $sum: 1 } } }
]);

console.log(c);

实际输出

[]

预期产量

// The value of count in this question is arbitrary

[
    { _id: "Critical", count: 30 },
    { _id: "Moderate", count: 33 },
    { _id: "Clean", count: 500 }
]

PS:如果您能向我推荐学习MongoDB聚合的最佳资源,我也将不胜感激

1 个答案:

答案 0 :(得分:1)

您需要在$ match阶段使用$in查询运算符,并在$ group阶段之前添加$unwind阶段。

db.collection.aggregate([
  {
    $match: {
      agent: {
        $in: [
          "5e2c98fc3d785252ce5b5693",
          "5e2c98fc3d785252ce5b5694"
        ]
      }
    }
  },
  {
    $project: {
      "mFiles.severity": true
    }
  },
  {
    $unwind: "$mFiles"
  },
  {
    $group: {
      _id: "$mFiles.severity",
      count: {
        $sum: 1
      }
    }
  }
])

Playground

样本数据:

[
  {
    "agent": "5e2c98fc3d785252ce5b5693",
    "mFiles": [
      {
        "title": "t1",
        "severity": "Critical"
      },
      {
        "title": "t2",
        "severity": "Critical"
      },
      {
        "title": "t3",
        "severity": "Moderate"
      },
      {
        "title": "t4",
        "severity": "Clean"
      }
    ]
  },
  {
    "agent": "5e2c98fc3d785252ce5b5694",
    "mFiles": [
      {
        "title": "t5",
        "severity": "Critical"
      },
      {
        "title": "t6",
        "severity": "Critical"
      },
      {
        "title": "t7",
        "severity": "Moderate"
      }
    ]
  }
]

输出:

[
  {
    "_id": "Moderate",
    "count": 2
  },
  {
    "_id": "Critical",
    "count": 4
  },
  {
    "_id": "Clean",
    "count": 1
  }
]

对于猫鼬整合:


//agents must be an array of objectIds like this 
//   [ObjectId("5e2c98fc3d785252ce5b5693"), ObjectId("5e2c98fc3d785252ce5b5694")]
//or ["5e2c98fc3d785252ce5b5693","5e2c98fc3d785252ce5b5694"]


const ObjectId = require("mongoose").Types.ObjectId;

let c = await Scan.aggregate([
  {
    $match: {
      agent: {
        $in: agents 
      }
    }
  },
  {
    $project: {
      "mFiles.severity": true
    }
  },
  {
    $unwind: "$mFiles"
  },
  {
    $group: {
      _id: "$mFiles.severity",
      count: {
        $sum: 1
      }
    }
  }
]);

学习mongodb聚合的最佳场所是official docs