如何在 $week mongodb 查询中没有匹配该周的记录时显示周为 0

how to show 0 for week when no record is matching that week in $week mongodb query

我的 collection 看起来像下面的细节

    /* 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}
        }
    }
])

查询将return创建的文档周数和数量如下

/* 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.

如何在没有创建记录的情况下获取文档计数为零的记录。

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

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

As $week can return a value between 0 and 53 I assume you expect 54 documents as a result with 0 or non-zero values for documentCount. To achieve that you should collect all your documents into one ($group-ing by null) 然后生成输出。

要生成一系列数字,您可以使用 $range operator and then you can generate the output using $map. To transform an array of documents into multiple docs you can use $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 to check if array of current docs contains the document (-1 otherwise) and $arrayElemAt to get existing document from docs. Last step ($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 作为开始和结束日期来获取数字。