与聚合匹配的项目不在mongodb中工作

时间:2015-11-17 09:02:19

标签: mongodb mongodb-query aggregation-framework

我正在尝试根据某些匹配条件获取数据。首先,我试过这个: 这里ending_date是完整日期格式

    Offer.aggregate([ 
    { 
        $match: { 
            carer_id : req.params.carer_id,
            status : 3
        }
    },
    {
        $group : {
            _id : { year: { $year : "$ending_date" }, month: { $month : "$ending_date" }}, 
            count : { $sum : 1 }
        }
    }], 
    function (err, res)
    { if (err) ; // TODO handle error 
         console.log(res); 
    });

给出了以下输出:

[ { _id: { year: 2015, month: 11 }, count: 2 } ]

现在我想检查一年,所以我正在尝试这个:

    Offer.aggregate([
    {
        $project: {
            myyear: {$year: "$ending_date"}
        }
    },
    { 
        $match: { 
            carer_id : req.params.carer_id,
            status : 3,
            $myyear : "2015"
        }
    },
    {
        $group : {
            _id : { year: { $year : "$ending_date" }, month: { $month : "$ending_date" }}, 
            count : { $sum : 1 }
        }
    }], 
    function (err, res)
    { if (err) ; // TODO handle error 
         console.log(res); 
    });

给出了以下输出:

 []

正如你所看到的,_id有2015年作为一年,所以当我匹配年份它应该是阵列。但我得到空数组。为什么这样?

有没有其他方法可以匹配年份整个日期时间?

以下是示例数据

{
    "_id": {
        "$oid": "56348e7938b1ab3c382d3363"
    },
    "carer_id": "55e6f647f081105c299bb45d",
    "user_id": "55f000a2878075c416ff9879",
    "starting_date": {
        "$date": "2015-10-15T05:41:00.000Z"
    },
    "ending_date": {
        "$date": "2015-11-19T10:03:00.000Z"
    },
    "amount": "850",
    "total_days": "25",
    "status": 3,
    "is_confirm": false,
    "__v": 0
}
{
    "_id": {
        "$oid": "563b5747d6e0a50300a1059a"
    },
    "carer_id": "55e6f647f081105c299bb45d",
    "user_id": "55f000a2878075c416ff9879",
    "starting_date": {
        "$date": "2015-11-06T04:40:00.000Z"
    },
    "ending_date": {
        "$date": "2015-11-16T04:40:00.000Z"
    },
    "amount": "25",
    "total_days": "10",
    "status": 3,
    "is_confirm": false,
    "__v": 0
}

3 个答案:

答案 0 :(得分:12)

你在这里做了很多错事,它确实需要一个解释,所以希望你能学到一些东西。

它是一条管道

这是最基本的概念,但是人们最常接受(甚至在继续使用之后)聚合“管道”就是这样,被称为“管道”的过程将输入馈送到每个阶段随着它的进展。想想“unix pipe”|

ps -ef | grep mongo | tee out.txt

毫无疑问,你已经看到了类似的东西,这是基本的概念,第一件事的输出转到下一件事,然后操纵给下一件事等等。

所以你要问的是基本问题:

    {
        $project: {
            myyear: {$year: "$ending_date"}
        }
    },
    { 
        $match: { 
            carer_id : req.params.carer_id,
            status : 3,
            $myyear : "2015"
        }
    },

考虑$project在这里做了些什么。您可以在输出中指定所需的字段,并将其“吐出”,并可能通过操作。它是否在“添加”文档中的字段中输出这些字段? 否它没有。只有你要求出来的东西才能实现,并且可以在以下管道阶段使用。

$match这里基本上要求不再存在的字段,因为你只在输出中要求一件事。同样的问题进一步发生,因为你再次询问你之前删除的字段,并且没有什么可以引用,但是$match已经删除了一切无法匹配的内容。

此外,这不是您输入的字段投影的工作方式

所以只需使用日期范围

        { "$match": { 
            "carer_id" : req.params.carer_id,
            "status" : 3,
            "ending_date": { 
                "$gte": new Date("2015-01-01"), 
                "$lt": new Date("2016-01-01")
            }
        }},
        { "$group": {
            "_id": { 
                "year": { "$year": "$ending_date" }, 
                "month": { "$month": "$ending_date" }
            }, 
            "count": { "$sum": 1 }
        }}

为什么呢?因为它才有意义。如果您想匹配“年份”,则提供全年的日期范围。我们可以使用$redact来愚蠢地匹配提取的年份值,但这只是浪费的处理时间。

这样做是最快的,并且实际上可以使用索引来更快地处理。所以不要解决问题,只要求你想要的日期范围。

答案 1 :(得分:7)

您忘记在以后$match$group投影您正在使用的字段。要快速解决此问题,请改用此查询:

Offer.aggregate([
{
    $project: {
        myyear: { $year: "$ending_date" },
        carer_id: 1,
        status: 1,
        ending_date: 1
    }
},
{ 
    $match: { 
        carer_id: req.params.carer_id,
        myyear: 2015,
        status: 3
    }
},
{
    $group: {
        _id: {
            year: { $year: "$ending_date" },
            month: { $month: "$ending_date" }
        }, 
        count: { $sum: 1 }
    }
}], 
function (err, res)
{
    if (err) {} // TODO handle error 
    console.log(res); 
});

尽管如此,Blakes Seven解释了如何在她的回答中提出更好的质询。我认为你应该尝试使用她的方法。

答案 2 :(得分:0)

如果您希望聚合工作正常进行,则必须使用$ addFields而不是$ project,以便将statuscarer_id保留在传递给$ match的对象中

{
        $addFields: {
            myyear: {$year: "$ending_date"}
        }
    },
    { 
        $match: { 
            carer_id : req.params.carer_id,
            status : 3,
            $myyear : "2015"
        }
    },