在嵌套文档

时间:2016-07-15 19:29:13

标签: java mongodb mongodb-query aggregation-framework

文件结构:

收集: myCollection

{
    "_id" : ObjectId("578818ba8872933f6452c5b5"),
    "user" : ObjectId("578818ba8872933f6452c5b5") ,
    "entries" : {
        "items" : [ 
            {
                "_id" : ObjectId("578819018872933f6452c5ba")
                "date" : ISODate("2016-07-14T22:57:58.715Z"),
                "values" : [ 
                    { "type" : A, "value" : 4 }, 
                    { "type" : B, "value" : 3 },  
                        ...
                ]
            }, 
            ...
        ]
    }
}

预期结果

  • 按日期分组(明天,忽略时间部分)
  • 每种类型的平均值

    { 
       "_id" : "2016-07-14",
       "values" : [
                    { "type" : "A", "avgValue" : 3.2 },
                    { "type" : "B", "avgValue" : 4.2 },
                    ...
                  ]
    }
    

试过这个但没有帮助

db.getCollection('myCollection').aggregate(
    [
        {
            "$match" : { 
                        "user" : ObjectId("578818ba8872933f6452c5b5") ,
                        "entries.items.date" : {"$gte" : new ISODate("2016-07-11T00:00:00.715Z"),"$lt" : new ISODate("2016-07-18T00:00:00.715Z")}
                     }
        },
        { "$unwind" : "entires.items"},
        { "$unwind" : "$entries.items.values"},
        {
            "$group" :  { "_id" : { '$year' : '$entries.items.date','$month' : '$entries.items.date','$day' : '$entries.items.date' },
                           "values" :   [{ "type": "$entries.items.values.type",
                                           "avgValue" : { "$avg" : "$entries.items.values.value"}
                                          }
                                       ]
                        }
        }
    ]
)

实现此结果的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

你可以制作2组,一组用于计算每种类型的平均值。日期,另一个推动类型&数组的平均值,并按日期分组:

aggregate.js

var ret = db.device.aggregate(
    [{
        "$match": {
            "user": ObjectId("578818ba8872933f6452c5b5"),
            "entries.items.date": {
                "$gte": new ISODate("2016-07-11T00:00:00.715Z"),
                "$lt": new ISODate("2016-07-18T00:00:00.715Z")
            }
        }
    }, {
        "$unwind": "$entries.items"
    }, {
        "$unwind": "$entries.items.values"
    }, {
        $project: {
            user: 1,
            entries: 1,
            day: {
                year: {
                    $year: "$entries.items.date"
                },
                month: {
                    $month: "$entries.items.date"
                },
                day: {
                    $dayOfMonth: "$entries.items.date"
                }
            }
        }
    }, {
        $project: {
            user: 1,
            entries: 1,
            day: {
                $concat: [{
                        $substr: ["$day.year", 0, 4]
                    },
                    "-", {
                        $substr: ["$day.month", 0, 2]
                    },
                    "-", {
                        $substr: ["$day.day", 0, 2]
                    }
                ]
            }
        }
    }, {
        $group: {
            "_id": {
                "date": "$day",
                "type": "$entries.items.values.type"
            },
            "avgValue": {
                "$avg": "$entries.items.values.value"
            }
        }
    }, {
        $group: {
            "_id": "$_id.date",
            "values": {
                "$push": {
                    "type": "$_id.type",
                    "avgValue": "$avgValue"
                }
            }
        }
    }]
).toArray();

printjson(ret);

用以下方法测试:

mongo --quiet 127.0.0.1/yourDB aggregate.js

我在分组之前使用了two projections,因为我没有让你的分组_id在我的系统上工作:

'$year' : '$entries.items.date','$month' : '$entries.items.date','$day' : '$entries.items.date'

我不知道它是否来自我的mongo 2.6版

结果给出了这样的结果:

[
    {
        "_id" : "2016-7-14",
        "values" : [
            {
                "type" : "B",
                "avgValue" : 4.5
            },
            {
                "type" : "A",
                "avgValue" : 6
            }
        ]
    }
]