如何在mongodb中处理部分周数据分组

时间:2015-02-08 02:12:38

标签: mongodb aggregation-framework

我有一些文档(股票的每日开盘价),如下所示:

/* 0 */
{
    "_id" : ObjectId("54d65597daf0910dfa8169b0"),
    "D" : ISODate("2014-12-29T00:00:00.000Z"),
    "O" : 104.98
}

/* 1 */
{
    "_id" : ObjectId("54d65597daf0910dfa8169af"),
    "D" : ISODate("2014-12-30T00:00:00.000Z"),
    "O" : 104.73
}

/* 2 */
{
    "_id" : ObjectId("54d65597daf0910dfa8169ae"),
    "D" : ISODate("2014-12-31T00:00:00.000Z"),
    "O" : 104.51
}

/* 3 */
{
    "_id" : ObjectId("54d65597daf0910dfa8169ad"),
    "D" : ISODate("2015-01-02T00:00:00.000Z"),
    "O" : 103.75
}

/* 4 */
{
    "_id" : ObjectId("54d65597daf0910dfa8169ac"),
    "D" : ISODate("2015-01-05T00:00:00.000Z"),
    "O" : 102.5
}

我希望按周汇总记录,这样我就可以获得每周平均开盘价。我的第一次尝试是使用:

db.ohlc.aggregate({
    $match: {
        D: {
            $gte: new ISODate('2014-12-28')
        }
    }
}, {
    $project: {
        year: {
            $year: '$D'
        },
        week: {
            $week: '$D'
        },
        O: 1
    }

}, {
    $group: {
        _id: {
            year: '$year',
            week: '$week'
        },
        O: {
            $avg: '$O'
        }
    }
}, {
    $sort: {
        _id: 1
    }
})

Bu我很快意识到结果不正确,因为2014年的最后一周(第52周)和2015年的第一周(第0周)都是部分周。通过这种聚合,我的平均价格为12 / 29-12 / 31/2014,另一个为2015年2月1日(这是2015年第一周的唯一交易日),但在我的申请中,我需要将2015年12月29日至2015年2月2日的数据分组。有什么建议吗?

3 个答案:

答案 0 :(得分:1)

要回答我自己的问题,诀窍是根据参考日期(1970-01-04)计算周数,并按该数字分组。您可以在http://midnightcodr.github.io/2015/02/07/OHLC-data-grouping-with-mongodb/查看我的新帖子了解详情。

答案 1 :(得分:1)

我将此candelization;allowDiskUsage一起使用,out和一些日期过滤器效果很好。也许你可以采用分组?

db.getCollection('market').aggregate(
[
    { $match: { date: { $exists: true } } },
    { $sort: { date: 1 } },
    { $project: { _id: 0, date: 1, rate: 1, amount: 1, tm15: { $mod: [ "$date", 900 ] } } }, 
    { $project: { _id: 0, date: 1, rate: 1, amount: 1, candleDate: { $subtract: [ "$date", "$tm15" ] } } },
    { $group: { _id: "$candleDate", open: { $first: '$rate' }, low: { $min: '$rate' }, high: { $max: '$rate' }, close: { $last: '$rate' }, volume: { $sum: '$amount' }, trades: { $sum: 1 } } }
])

答案 2 :(得分:0)

根据我的经验,这不是一个解决问题的好方法。为什么?这肯定不会扩展,所需的计算量非常耗费,特别是进行分组。

在您的情况下,我要做的是将部分应用程序逻辑移动到数据库中的文档。

我的第一个方法是添加一个"周"将声明样本所属日期的上一个(或下一个)星期日的字段。这在插入时很容易做到。然后,您只需运行该字段的聚合方法分组。如果您想获得更高的性能,请为{ symbol : 1, week : 1 }添加索引并在聚合中进行排序。

我的第二种方法,如果你计划进行大量这种类型的聚合,基本上就是拥有以每周方式对样本进行分组的文档。像这样:

{
    week : <Day Representing Week>,
    prices: [
       { Day Sample }, ...
    ]
}

然后您可以直接处理这些文档。这将有助于您以显着的方式减少索引,从而加快速度。