【问题标题】:Aggregate with count of sub documents matching the condition and grouping聚合与条件和分组匹配的子文档的数量
【发布时间】:2015-11-18 19:12:58
【问题描述】:

我收集的文件如下:

{
    "_id" : ObjectId("55d4410544c96d6f6578f893"),
    "executionProject" : "Project1",
    "suiteList" : [ 
        {
            "suiteStatus" : "PASS"
        }
    ],
    "runEndTime" : ISODate("2015-08-19T08:40:47.049Z"),
    "runStartTime" : ISODate("2015-08-19T08:40:37.621Z"),
    "runStatus" : "PASS",
    "__v" : 1
}

{
    "_id" : ObjectId("55d44eb4c0422e7b8bffe76b"),
    "executionProject" : "Project1",
    "suiteList" : [ 
        {
            "suiteStatus" : "PASS"
        }
    ],
    "runEndTime" : ISODate("2015-08-19T09:39:13.528Z"),
    "runStartTime" : ISODate("2015-08-19T09:39:00.406Z"),
    "runStatus" : "PASS",
    "__v" : 1
}

{
    "_id" : ObjectId("55d44f0bc0422e7b8bffe76f"),
    "executionProject" : "Project1",
    "suiteList" : [ 
        {
            "suiteStatus" : "FAIL"
        }
    ],
    "runEndTime" : ISODate("2015-08-19T09:46:31.108Z"),
    "runStartTime" : ISODate("2015-08-19T09:40:27.377Z"),
    "runStatus" : "PASS",
    "__v" : 1
}

{
    "_id" : ObjectId("55d463d0c0422e7b8bffe789"),
    "executionProject" : "Project2",
    "suiteList" : [ 
        {
            "suiteStatus" : "PASS"
        },
        {
            "suiteStatus" : "PASS"
        }
    ],
    "runEndTime" : ISODate("2015-08-19T11:09:52.537Z"),
    "runStartTime" : ISODate("2015-08-19T11:09:04.539Z"),
    "runStatus" : "FAIL",
    "__v" : 1
}

{
    "_id" : ObjectId("55d464ebc0422e7b8bffe7c2"),
    "executionProject" : "Project3",
    "suiteList" : [ 
        {
            "suiteStatus" : "FAIL"
        }
    ],
    "runEndTime" : ISODate("2015-08-19T11:18:41.460Z"),
    "runStartTime" : ISODate("2015-08-19T11:13:47.268Z"),
    "runStatus" : "FAIL",
    "__v" : 10
} 

我期望输出如下:

[
    {
        "executionProject": "Project1",
        "suite-pass": 0,
        "suite-fail": 1,
        "runEndTime": ISODate("2015-08-19T09:46:31.108Z")
    },
    {
        "executionProject": "Project2",
        "suite-pass": 2,
        "suite-fail": 0,
        "runEndTime": ISODate("2015-08-19T11:09:52.537Z")
    },
    {
        "executionProject": "Project3",
        "suite-pass": 0,
        "suite-fail": 1,
        "runEndTime": ISODate("2015-08-19T11:18:41.460Z")
    },
]

我想按项目分组并按 runEndTime 排序并显示 suiteList 的通过和失败计数。

我按照 Blakes 在Mongodb: Group by element and show the sub-document count based on condition and sort the document by date 中的建议尝试了这个:

db.testruns.aggregate([
      { "$sort": { "runEndTime": 1 } },
      { "$group": {
      "_id": "$executionProject",
        "suite-pass": {
          "$last": {
            "$cond": [
              { "$anyElementTrue": {
                "$map": {
                  "input": "$suiteList",
                  "as": "suite",
                  "in": {
                    "$eq": [ "$$suite.suiteStatus", "PASS" ]
                  }
                }
              }},
              1,
              0
            ]
          }
        },
        "suite-fail": {
          "$last": {
            "$cond": [
              { "$anyElementTrue": {
                "$map": {
                  "input": "$suiteList",
                  "as": "suite",
                  "in": {
                    "$eq": [ "$$suite.suiteStatus", "FAIL" ]
                  }
                }
              }},
              1,
              0
            ]
          }
        },
        "runEndTime": { "$last": "$runEndTime" }
      }},
      { "$sort": { "runEndTime": 1 } }
    ]);

我期待 Project2suite-pass 计数为 2,因为 suiteList 中有 2 个元素,但它返回 1。

【问题讨论】:

    标签: mongodb mongoose mongodb-query aggregation-framework


    【解决方案1】:

    您应该已经正确阅读了答案,因为已经有另一个替代列表和解释为什么您想要的预期结果与您使用的结果不同。

    相反,您想要这个,它尊重可能的多个“PASS”或“FAIL”:

      Model.aggregate(
        [
          { "$sort": { "executionProject": 1, "runEndTime": 1 } },
          { "$group": {
            "_id": "$executionProject",
            "suiteList": { "$last": "$suiteList" },
            "runEndTime": { "$last": "$runEndTime" }
          }},
          { "$unwind": "$suiteList" },
          { "$group": {
            "_id": "$_id",
            "suite-pass": { 
              "$sum": {
                "$cond": [
                  { "$eq": [ "$suiteList.suiteStatus", "PASS" ] },
                  1,
                  0
                ]
              }
            },
            "suite-fail": { 
              "$sum": {
                "$cond": [
                  { "$eq": [ "$suiteList.suiteStatus", "FAIL" ] },
                  1,
                  0
                ]
              }
            },
            "runEndTime": {"$first": "$runEndTime"}
          }},
          { "$sort": { "runEndTime": 1 }}
        ],
        function(err,result) {
    
        }
      );
    

    这是一种方法的“组合”。第一个是按照您的预期通过 runTime 获得“最后一个”。接下来是分解数组,这一次实际上“总结”可能出现的通过或失败,而不是只记录数组中通过或失败的1,实际的“通过”或“失败”被计算在内。

    有结果:

    {
            "_id" : "Project1",
            "suite-pass" : 0,
            "suite-fail" : 1,
            "runEndTime" : ISODate("2015-08-19T09:46:31.108Z")
    }
    {
            "_id" : "Project2",
            "suite-pass" : 2,
            "suite-fail" : 0,
            "runEndTime" : ISODate("2015-08-19T11:09:52.537Z")
    }
    {
            "_id" : "Project3",
            "suite-pass" : 0,
            "suite-fail" : 1,
            "runEndTime" : ISODate("2015-08-19T11:18:41.460Z")
    }
    

    【讨论】:

    • 你是个天才。如果你在这附近,我想请你喝杯啤酒。
    【解决方案2】:

    展开suiteList 并在group 中使用$sum,如下所示:

    db.testruns.aggregate({
        "$unwind": "$suiteList"
    }, {
        "$group": {
            "_id": "$executionProject",
            "suite-pass": {
                "$sum": {
                    "$cond": {
                        "if": {
                            "$eq": ["$suiteList.suiteStatus", "PASS"]
                        },
                        "then": 1,
                        "else": 0
                    }
                }
            },
            "suite-fail": {
                "$sum": {
                    "$cond": {
                        "if": {
                            "$eq": ["$suiteList.suiteStatus", "FAIL"]
                        },
                        "then": 1,
                        "else": 0
                    }
                }
            },
            "runEndTime": {
                "$last": "$runEndTime"
            }
        }
    }, {
        "$sort": {
            "runEndTime": 1
        }
    })
    

    【讨论】:

    • 这会将Project1 的套件通过计数返回为 2,套件失败计数为 1。我期待套件通过计数为 0,套件失败计数为 1。
    • @Vimal 您确实意识到这是我最初给您的答案的直接复制粘贴,然后您才明确表示您想要“最后一个”而不是“总和”。让您知道自己得到了什么回报。
    猜你喜欢
    • 2018-05-29
    • 2020-01-09
    • 2013-04-08
    • 1970-01-01
    • 2017-07-21
    • 1970-01-01
    • 2017-05-18
    • 1970-01-01
    • 2015-05-29
    相关资源
    最近更新 更多