Symfony/Doctrine/MongoDB获取每N个项目


Symfony/Doctrine/MongoDB Get every Nth item

我有一个数据集,每天每5秒包含一个数据点。这将导致每天有17280个项目的数据集。这个集合太大了,我希望它更小(我用这些项目来画一张图)。

由于图表的x轴是随时间变化的,我认为每个数据点5分钟的间隔就足够了。这将返回到每天288个数据点。少了很多,好得足以制作一张图。

我的MongoCollection看起来像这样:

{
    "timestamp":"12323455",
    "someKey":123,
    "someOtherKey": 345,
    "someOtherOtherKey": 6789
}

数据每隔5秒就会被发布到数据库中。因此,每个结果的时间戳将相差5秒。

由于我的x轴被划分为5分钟序列,我想计算这5分钟内someKeysomeOtherKeysomeOtherOtherkey的平均值。这个新的平均值将是我图表中的数据点之一。

如何在平均间隔5分钟的情况下获得1天的所有数据点?(每天288个数据点)。

就目前而言,我正在从今天午夜开始选择每一份文件:

$result = $collection
    ->createQueryBuilder()
    ->field('timestamp')->gte($todayMidnight)
    ->sort('timestamp', 'DSC')
    ->getQuery()
    ->execute();

如何过滤此数据列表(在同一查询中)以获得每5分钟的数据点(数据点是这5分钟内的平均值)?

如果能用原则构建这个查询,那就太好了,因为我在symfony应用程序中需要它。

编辑我试着让我的查询首先在mongoshell中工作。正如在评论中建议的那样,我应该开始使用聚合。

到目前为止,我提出的问题是基于stackoverflow 提出的另一个问题

这是当前的查询:

db.Pizza.aggregate([
    {
        $match:
        {
            timestamp: {$gte: 1464559200}
        }
    }, 
    {
        $group:
        {
            _id:
            {
                $subtract: [
                    "$timestamp", 
                    {"$mod": ["$timestamp", 300]}
                ]
            },
            "timestamp":{"$first":"$timestamp"}, 
            "someKey":{"$first":"$someKey"},
            "someOtherKey":{"$first":"$someOtherKey"},
            "someOtherOtherKey":{"$first":"$someOtherOtherKey"}
        }
    }
])

这个查询将给我从今天午夜开始每300秒(5分钟)的最后结果。我希望它在这300秒内获取所有文档,并计算列someKeysomeOtherKeysomeOtherOtherKey 的平均值

因此,如果我们以这个数据集为例:

{
    "timestamp":"1464559215",
    "someKey":123,
    "someOtherKey": 345,
    "someOtherOtherKey": 6789
},
{
    "timestamp":"1464559220",
    "someKey":54,
    "someOtherKey": 20,
    "someOtherOtherKey": 511
},
{
    "timestamp":"1464559225",
    "someKey":654,
    "someOtherKey": 10,
    "someOtherOtherKey": 80
},
{
    "timestamp":"1464559505",
    "someKey":90,
    "someOtherKey": 51,
    "someOtherOtherKey": 1
}

查询应返回2行,即:

{
    "timestamp":"1464559225",
    "someKey":277,
    "someOtherKey": 125,
    "someOtherOtherKey": 2460
},
{
    "timestamp":"1464559505",
    "someKey":90,
    "someOtherKey": 51,
    "someOtherOtherKey": 1
}

第一个结果是这样计算的:

Result 1 - someKey = (123+54+654)/3 = 277
Result 1 - someOtherKey = (345+20+10)/3 = 125
Result 1 - someOtherOtherKey = (6789+511+80)/3 = 2460

如何在具有聚合函数的mongoshell中进行此计算

根据stackoverflow上给出的答案,我成功地得到了我想要的东西。

这是我必须进行的一个大的聚合查询,以返回所有结果:

db.Pizza.aggregate([
    {
        $match:
        {
            timestamp: {$gte: 1464559200}
        }
    }, 
    {
        $group: 
        {
            _id:
            {
                $subtract: [
                    '$timestamp', 
                    {$mod: ['$timestamp', 300]}
                ]
            },
            timestamp: {$last: '$timestamp'}, 
            someKey: {$avg: '$someKey'},
            someOtherKey: {$avg: '$someOtherKey'}, 
            someOtherOtherKey: {$avg: '$someOtherOtherKey'}
        }
    },
    {
        $project: 
        {
            _id: 0, 
            timestamp: '$timestamp', 
            someKey: '$someKey', 
            someOtherKey:'$someOtherKey',
            someOtherOtherKey:'$someOtherOtherKey'
        }
    }
])

比赛部分是为了在今天午夜(今天午夜的时间戳)之后获得每一个结果。

小组部分是最有趣的部分。在这里,我们循环浏览我们找到的每个文档,并每300秒(5分钟)计算一个模数,然后用模数运算的最后结果填充属性时间戳。

Project部分需要从实际结果中删除_id,因为结果不再代表数据库中的某些内容。

给定答案,此答案基于:

MongoDB-同时聚合多个变量的最大/最小/平均

如何在mongodb php 中进行减法

MongoDB:聚合框架:根据分组ID 获取最后日期的文档

条令解决方案

$collection->aggregate([
    [
        '$match' => [
            'timestamp' => ['$gte' => 1464559200]
        ]
    ],
    [
        '$group' => [
            '_id' => [
                '$subtract' => [
                    '$timestamp',
                    [
                        '$mod' => ['$timestamp',300]
                    ]
                ]
            ],
            'timestamp' => [
                '$last' => '$timestamp'
            ],
            $someKey => [
                '$avg' => '$'.$someKey
            ],
            $someOtherKey => [
                '$avg' => '$'.$someOtherKey
            ],
            $someOtherOtherKey => [
                '$avg' => '$'.$someOtherOtherKey
            ]
        ]
    ]
]);