在聚合中具有Match的项目在mongodb中不起作用

nr9pn0ug  于 2023-03-29  发布在  Go
关注(0)|答案(4)|浏览(277)

我试图根据一些匹配条件获取数据。首先我尝试了这个:这里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年,所以当我匹配year时,它应该在数组中。但是我得到了null数组。为什么会这样?
有没有其他方法可以只匹配整个日期时间的年份?
下面是示例数据

{
    "_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
}
4si2a6ki

4si2a6ki1#

您忘记投影稍后在$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在她的回答中解释了如何做一个更好的查询。我认为你应该试着用她的方法来代替。

qmb5sa22

qmb5sa222#

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

管道

这是最基本的概念,但人们并不经常(甚至在继续使用之后)注意到聚合“管道”就是这样,被“管道化”的进程将输入馈送到每个阶段。想想“unix管道”|

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来匹配提取的年份值,但这只是浪费处理时间。
这样做是最快的处理,实际上可以使用一个索引来处理更快。所以不要思考问题,只是要求您想要的日期范围。

uxhixvfz

uxhixvfz3#

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

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

w80xi6nr4#

正确的查询如下所示,您可以使用相关的内容:

Offer.aggregate([
   { $match:{ isPinSet:true } },
   { $project:{ "_id":1,"pVersion":1,isPinSet:1 } }
])

相关问题