最近在学习 基金投资,作为搞技术的,肯定不可能止步于了解皮毛知识。所以写了一个程序,去爬取基金的一些数据,然后用MongoDB做数据分析。
昨天在分析采集的数据时,遇到一个场景,我想统计某一只基金的历史净值数据,看哪些基金的数据比较全面。
我的数据存储结构是这样的:
{
"_id" : ObjectId("5d048672f241304ded366682"),
"fund_code" : "110023",
"updated_at" : ISODate("2019-06-15T05:47:30.000Z"),
"created_at" : ISODate("2019-06-15T05:47:30.000Z"),
"day_net_info" : [
{
"date" : "20140102",
"net" : 1.328,
"sum" : 1.328
},
{
"date" : "20150105",
"net" : 1.269,
"sum" : 1.269
},
{
"date" : "20140103",
"net" : 1.324,
"sum" : 1.324
}]
}
上面结构中,每天的基金净值数据都存在 day_net_info 这个字段中,所以上面的统计需求,转化为编程需求就是:按MongoDB按某个字段(数组)长度排序,取出数据最全的前十只基金。
我的实现方式是这样的:
db.fund_daynet.aggregate([
{$unwind: '$day_net_info'},
{$group: {_id: '$_id',day_net_info: {$push: '$day_net_info'},cnt: {$sum: 1}}},
{$sort: {cnt:-1}},
{$limit: 10}
])
最终确实实现了,但是效率还是很低的。2010年到现在将近十年的基金净值数据,使用 unwind 平铺转化后,有400多万条数据,再分组和统计,计算后最终的得出结果的时间比较长,目前没有找到更好的解决方案。
================
2019-06-17 改良方法
周六解决这个问题的时候比较着急,回头我想了一下,还真有个方法可以统计元素个数,所以改良方法如下:
db.fund_daynet.aggregate([
{$project:{fund_code:1, cnt:{$size:'$day_net_info'}}},
{$sort: {cnt:-1}},
{$limit: 10}
])
这个方法的原理是使用 $size 方法统计元素个数,然后把返回值作为 $sort 的参数进行排序,执行速度就比之前的方法快多了。
本文为 陈华 原创,欢迎转载,但请注明出处:http://ichenhua.cn/read/45
- 下一篇:
- Linux系统下安装php-ssh2扩展