在$ week mongodb查询中,当没有记录与该周匹配时,如何在一周中显示0

时间:2018-07-23 08:48:14

标签: mongodb aggregation-framework aggregate week-number

我的收藏集如下所示

db.collectionName.aggregate([

    //where query
    { "$match": {  $and:[{CreatedOn:{$lte:ISODate("2018-07-14T13:59:08.266+05:30")}},{CreatedOn:{$gte:ISODate("2018-06-10T13:59:08.266+05:30")}}] } },
    //distinct column 
    {
        "$group": {
            _id: {$week: '$CreatedOn'},
            documentCount: {$sum: 1}
        }
    }
])

我有如下查询

/* 1 */
{
    "_id" : 26,
    "documentCount" : 1
},

/* 2 */
{
    "_id" : 25,
    "documentCount" : 1
},

/* 3 */
{
    "_id" : 24,
    "documentCount" : 9
},

/* 4 */
{
    "_id" : 23,
    "documentCount" : 2
}

查询将返回如下创建的文档的星期数和数量

"_id":23

在_id上方是星期数。如果在上述结果中,weekNumber:23未创建任何记录,则查询仅给出3条记录,删除了/* 4 */ { "_id" : 23, "documentCount" : 0 }

在没有创建记录的情况下如何获取documentcount为零的记录。

就像上面的示例一样,当没有_id的记录时:23应该像下面这样

module.exports = {
    "src_folders": [
        "suites"
    ],
    "output_folder": "reports",
    "custom_commands_path": "commands",
    "page_objects_path": "pageObjects",
    "globals_path": "globals.js",
    "selenium": {
        "start_process": true,
        "server_path": seleniumServer.path,
        "host": "127.0.0.1",
        "port": 4444,
        "log_path": "logs",
        "cli_args": {
            "webdriver.chrome.driver": chromedriver.path,
            "webdriver.firefox.driver": '/usr/bin/geckodriver',
            "webdriver.safari.driver": '/usr/bin/safaridriver'
        }
    },
    "test_settings": {
        "default": {
            "launch_url": "http://google.com",
            "screenshots": {
                "enabled": true,
                "on_failure" : true,
                "on_error" : true
            },
            "globals": {
                "waitForConditionTimeout": 5000,
                "retryAssertionTimeout": 5000
            },
            "desiredCapabilities": {
                "browserName": "safari",
                "browserVersion": "12",
                "technologyPreview": true
            },
            "skip_testcases_on_fail": false,
            "end_session_on_fail": false
        }
    }
};

1 个答案:

答案 0 :(得分:1)

由于$week可以返回053之间的值,因此我假设您期望54文档的结果是0或非零值documentCount。为此,您应该将所有文档收集到一个文档中(null$group),然后生成输出。

要生成一系列数字,可以使用$range运算符,然后可以使用$map生成输出。要将文档数组转换为多个文档,可以使用$unwind

db.collectionName.aggregate([
    //where query
    { "$match": {  $and:[{CreatedOn:{$lte:ISODate("2018-07-14T13:59:08.266+05:30")}},{CreatedOn:{$gte:ISODate("2018-06-10T13:59:08.266+05:30")}}] } },
    //distinct column 
    {
        "$group": {
            _id: {$week: '$CreatedOn'},
            documentCount: {$sum: 1}
        }
    },
    {
        $group: {
            _id: null,
            docs: { $push: "$$ROOT" }
        }
    },
    {
        $project: {
            docs: {
                $map: {
                    input: { $range: [ {$week:ISODate("2018-06-10T13:59:08.266+05:30")}, {$week:ISODate("2018-07-14T13:59:08.266+05:30")}]},
                    as: "weekNumber",
                    in: {
                        $let: {
                            vars: { index: { $indexOfArray: [ "$docs._id", "$$weekNumber" ] } },
                            in: {
                                $cond: {
                                    if: { $eq: [ "$$index", -1 ] },
                                    then: { _id: "$$weekNumber", documentCount: 0 },
                                    else: { $arrayElemAt: [ "$docs", "$$index" ] }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    {
        $unwind: "$docs"
    },
    {
        $replaceRoot: {
            newRoot: "$docs"
        }
    }
])

使用$indexOfArray检查当前文档数组是否包含文档(否则为-1),并使用$arrayElemAtdocs获取现有文档。最后一步($replaceRoot)只是摆脱了一层嵌套(docs)。输出:

{ "_id" : 0, "documentCount" : 0 }
{ "_id" : 1, "documentCount" : 0 }
{ "_id" : 2, "documentCount" : 0 }
...
{ "_id" : 22, "documentCount" : 0 }
{ "_id" : 23, "documentCount" : 2 }
{ "_id" : 24, "documentCount" : 9 }
{ "_id" : 25, "documentCount" : 1 }
{ "_id" : 26, "documentCount" : 1 }
{ "_id" : 27, "documentCount" : 0 }
...
{ "_id" : 52, "documentCount" : 0 }
{ "_id" : 53, "documentCount" : 0 }

您可以轻松定制返回的结果,从而修改$map阶段的输入。例如,您也可以传递一个像input: [21, 22, 23, 24]这样的const数组。

编辑:要获取指定日期之间的星期数,可以使用$week作为开始和结束日期以获取数字。