首页 文章

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

提问于
浏览
6

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

由于图表的x轴随着时间的推移,我确定每个数据点的间隔为5分钟就足够了 . 这将每天返回 288 datapoints . 制作图表要少得多,也足够好 .

我的MongoCollection看起来像这样:

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

数据每5秒发布到数据库中 . 因此,每个结果的时间戳将相差5秒 .

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

如何从1天获得所有数据点,每个平均5分钟相互之间? (每天288个数据点) .

至于现在我从今天午夜开始选择每个文件:

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

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

使用 doctrine 构建此查询会很好,因为我需要在我的symfony应用程序中使用它 .

EDIT 我试图在mongoshell工作中首先获取我的查询 . 如在建议的评论中我应该开始使用aggregation .

我到目前为止所提出的查询是基于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

How would one make this calculation within the mongoshell with the aggregation function?

1 回答

  • 2

    根据给定的回答在这里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 - Aggregate max/min/average for multiple variables at once

    How to subtract in mongodb php

    MongoDB : Aggregation framework : Get last dated document per grouping ID

    Doctrine Solution

    $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
                ]
            ]
        ]
    ]);
    

相关问题