【问题标题】:how to show 0 for week when no record is matching that week in $week mongodb query如何在 $week mongodb 查询中没有记录匹配该周时显示 0 周
【发布时间】:2018-12-30 16:08:02
【问题描述】:

我的收藏详情如下所示

    /* 1 createdAt:6/13/2018, 5:17:07 PM*/
{   "_id" : ObjectId("5b21043b18f3bc7c0be3414c"),   
    "Number" : 242,
    "State" : "2",
    "City" : "3",
    "Website" : "",
    "Contact_Person_Name" : "Ajithmullassery",  
    "CreatedById" : "Admin",
    "UpdatedById" : "Admin",    
    "IsActive" : true,
    "UpdatedOn" : ISODate("2018-06-13T17:17:07.313+05:30"),
    "CreatedOn" : ISODate("2018-06-13T17:17:07.313+05:30")  
},

/* 2 createdAt:6/13/2018, 6:45:42 PM*/
{
    "_id" : ObjectId("5b2118fe18f3bc7c0be3415b"),   
    "Number" : 243,
    "State" : "1",
    "City" : "143",
    "Website" : "",
    "Contact_Person_Name" : "sachitkumar",  
    "CreatedById" : "vinoth",
    "UpdatedById" : "Admin",    
    "IsActive" : true,
    "UpdatedOn" : ISODate("2018-06-13T18:45:42.590+05:30"),
    "CreatedOn" : ISODate("2018-06-13T18:45:42.590+05:30")

},

/* 3 createdAt:6/18/2018, 5:34:33 PM*/
{
    "_id" : ObjectId("5b279fd118f3bc7c0be34166"),   
    "Number" : 244,
    "State" : "0",
    "City" : "8",
    "Website" : "",
    "Contact_Person_Name" : "Akshay",   
    "CreatedById" : "vinoth",
    "UpdatedById" : "Admin",    
    "IsActive" : true,
    "UpdatedOn" : ISODate("2018-06-18T17:34:33.270+05:30"),
    "CreatedOn" : ISODate("2018-06-18T17:34:33.270+05:30")

},

/* 4 createdAt:6/20/2018, 1:02:21 PM*/
{
    "_id" : ObjectId("5b2a030518f3bc7c0be3416d"),   
    "Number" : 245,
    "State" : "5",
    "City" : "6",
    "Website" : "",
    "Contact_Person_Name" : "Dr DS Mithra", 
    "CreatedById" : "vinoth",
    "UpdatedById" : "Admin",
    "FacilityID" : "594387f5e2de7be83be5d5f1",
    "IsActive" : true,
    "UpdatedOn" : ISODate("2018-06-20T13:02:21.887+05:30"),
    "CreatedOn" : ISODate("2018-06-20T13:02:21.887+05:30")
},

/* 5 createdAt:6/20/2018, 1:08:58 PM*/
{
    "_id" : ObjectId("5b2a049218f3bc7c0be3416e"),   
    "Number" : 245,
    "State" : "5",
    "City" : "6",
    "Website" : "",
    "Contact_Person_Name" : "Ramaswamy Manickam",   
    "CreatedById" : "vinoth",
    "UpdatedById" : "Admin",    
    "IsActive" : true,
    "UpdatedOn" : ISODate("2018-06-20T13:08:58.040+05:30"),
    "CreatedOn" : ISODate("2018-06-20T13:08:58.040+05:30")

}

我有如下查询

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 是周数。如果在上述结果中 weekNumber : 23 没有创建记录,则查询仅给出 3 条记录,删除 "_id":23

没有创建记录时如何获取documentcount为零的记录。

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

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

【问题讨论】:

    标签: mongodb aggregation-framework aggregate week-number


    【解决方案1】:

    由于$week 可以返回介于053 之间的值,我假设您期望54 文档具有0documentCount 的非零值。要实现这一点,您应该将所有文档收集到一个($group-ing by null),然后生成输出。

    要生成一系列数字,您可以使用$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]

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

    【讨论】:

    • 我们在哪里可以通过匹配或任何条件,就像我提到的问题
    • @charantej 修改了我的答案
    • 它没有给出任何结果,只有 19 条记录,所有文档计数为 0。
    • 您可以将范围限制为仅查看输入日期后的几周。类似{ $range: [ {$week:ISODate("2018-06-10T13:59:08.266+05:30")}, {$week:ISODate("2018-07-14T13:59:08.266+05:30")}]}
    • @charantej 我前段时间看到过类似的问题。您必须将该范围指定为 ($week)*$year - ($week)*$year,然后使用 $divide 和 modulo 来获得周和年。让我知道是否需要更多帮助或只是创建另一个问题,以便我能够解释
    猜你喜欢
    • 1970-01-01
    • 2015-07-24
    • 2014-09-20
    • 1970-01-01
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-09
    相关资源
    最近更新 更多