在展开之前使用数组字段匹配

时间:2018-01-15 09:43:14

标签: mongodb aggregation-framework

我有以下文档结构:

{
    "_id" : ObjectId("5a16b7cf930a1e000465d1c5"),
    "trackerId" : ObjectId("5a16b7b8930a1e000465d1c1"),
    "trackingEvents" : [ 
        {
            "type" : "checkin",
            "timestamp" : ISODate("2017-11-23T11:57:43.710Z"),
        }, 
        {
            "type" : "connectivity",
            "timestamp" : ISODate("2017-11-23T11:57:47.011Z"),
        }, 
        {
            "type" : "power",
            "timestamp" : ISODate("2017-11-23T11:57:47.036Z"),
        }
    ]
}

我想设置一个查询来计算所有trackingEvents发生的< "type":"power" trackingEvents的数量,其中db.getCollection('trackerEvents').aggregate( [ {$unwind: "$trackingEvents"}, {$match: { "trackingEvents.type": "power", "trackingEvents.timestamp": { "$gt": { "$humanTime": "1 month ago" //redash operator } } } }, { "$group": { "_id": { "$dateToString": { "format": "%Y-%m-%d", "date": "$trackingEvents.timestamp" } }, count: {$sum: 1} } }, , { $sort : { "_id":1 } } ]) 按日分组1个月前。并且以下查询工作正常,除了它不够快的事实:

$match

但是,此查询未通过代码审核,因为我的同事建议交换$unwind$match运算符,以便$unwind$match之前进行,以提高性能的查询。如果我交换这两个运算符,我会得到不同的结果,有人可以建议在$unwind之前如何对{{1}}文档的数组元素进行建议吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

您可以使用 $match 运算符来提前过滤文档,然后在 {{之前在数组级别 $filter 进行过滤3}}

var oneMonthAgo = new Date();
oneMonthAgo.setMonth(oneMonthAgo.getMonth()-1);
// var oneMonthAgo = moment().subtract(1, "months").unix();

db.getCollection('trackerEvents').aggregate([
    { 
        "$match": { 
            "trackingEvents.type": "power",
            "trackingEvents.timestamp": { "$gt": oneMonthAgo }
        } 
    },
    {
        "$project": {
            "trackingEvents": {
                "$filter": {
                    "input": "$trackingEvents",
                    "as": "event",
                    "cond": {
                        "$and": [
                            { "$eq": ["$$event.type", "power"] },
                            { "$gt": ["$$event.timestamp", oneMonthAgo] }
                        ]
                    }
                }               
            }
        }
    },
    { "$unwind": "$trackingEvents" },
    {
        "$group": {
            "_id": {
                "$dateToString": {
                    "format": "%Y-%m-%d",
                    "date": "$trackingEvents.timestamp"
                }
            },
            "count": { "$sum": 1}
        }
    },
    { "$sort": { "_id": 1 } }
]);