Mongodb:按元素分组并根据条件显示子文档计数并按日期对文档进行排序

时间:2015-08-24 05:39:44

标签: node.js mongodb mongoose mongodb-query aggregation-framework

我收集的文件如下:

{
    "_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" : "FAIL"
        },
        {
            "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": 1,
        "suite-fail": 1,
        "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的传递和失败计数。

我知道如何获得套件通过和所有运行的失败计数,但不知道如何分组和订购。请帮助。

1 个答案:

答案 0 :(得分:1)

使用$cond运算符的聚合框架似乎就是您所追求的:

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

  });

这有条件地测试“PASS”或“FAIL”的值,并将这些值返回$sum下的$group累加器。以同样的方式,您为每个分组文档的相关日期取$max值。

最后一件事就是那个日期$sort

如果“suiteList”实际上只会包含一个“PASS”和一个“FAIL”,那么你甚至可能在没有使用数组上的$unwind的情况下逃脱:

  Model.aggregate(
    [
      { "$group": {
        "_id": "$executionProject",
        "suite-pass": {
          "$sum": {
            "$cond": [
              { "$anyElementTrue": {
                "$map": {
                  "input": "$suiteList",
                  "as": "suite",
                  "in": {
                    "$eq": [ "$$suite.suiteStatus", "PASS" ]
                  }
                }
              }},
              1,
              0
            ]
          }
        },
        "suite-fail": {
          "$sum": {
            "$cond": [
              { "$anyElementTrue": {
                "$map": {
                  "input": "$suiteList",
                  "as": "suite",
                  "in": {
                    "$eq": [ "$$suite.suiteStatus", "FAIL" ]
                  }
                }
              }},
              1,
              0
            ]
          }
        },
        "runEndTime": { "$max": "$runEndTime" }
      }},
      { "$sort": { "runEndTime": 1 }}
    ],
    function(err,results) {

    }
  )

其中的$map$anyElementTrue可以类似地测试匹配数组中应该计算的条件。因此,只要每个文档的“匹配数”无关紧要,那就没关系。

在这里符合这些条件的数据,然后产生相同的结果:

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

要获取“最后”项,请先$sort,然后将$sum累加器替换为$last累加器:

  Model.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 } }
    ],
    function(err,results) {

    }
  );

产生:

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