Python / Django:在MySQL数据库上模拟多维层
我正在做一个Django项目,需要对同一组数据提供很多不同的可视化展示(比如每个月的平均值、每年的平均值,或者某个地点的平均值等等)。
我在大学时用过一次OLAP数据库,觉得这可能适合我的需求,但实际上它对我来说太复杂了。其实我的数据量并不大,所以我不需要什么优化,只想找到一种方法,能展示同一组数据的不同可视化,而不需要写一千遍相同的代码。
所以,总结一下,我需要一个Python库:
- 能够模拟一个多维数据库(OLAP风格的会很好,因为我觉得这种结构很方便:星型结构,等等)
- 不干扰现有的MySQL数据库,因为我不能对它进行任何修改
- 易于使用,因为如果不简单的话,换个工具也没什么意义。
4 个回答
0
你有 Python 的 defaultdict
字典。
如果你的数据量不大,可以直接把所有数据查询出来,然后用这些数据创建一些字典,里面存储计数、总和等等。
“星型模式”其实就是一种简单的数据库结构,适合预算有限的人使用。在这种结构中,维度(也就是字典)会指向一些行的列表。你可以对这些行的列表进行汇总,来创建汇总字典。
d1_sum= defaultdict( int )
d1_count= defaultdict( count )
d2_sum = defaultdict( int )
for row in MyFactTable.objects.all():
d1_sum[row.attr1] += row.fact1
d1_count[row.attr1] += 1
d2_sum[row.attr2] += some_function( row.fact2 )
etc.
1
为什么不直接使用标准的ORM聚合函数呢?可以参考这个链接:http://docs.djangoproject.com/en/dev/topics/db/aggregation/
如果你觉得某个字段的性能可能会受到影响,你可以考虑对这个字段进行去规范化处理。
2
好的……我终于想出了自己的解决办法(https://code.google.com/p/django-cube/),因为我找不到我想要的东西。
有一个这样的模型:
class Instrument(models.Model):
name = models.CharField(max_length=100)
class Musician(models.Model):
firstname = models.CharField(max_length=100)
instrument = models.ForeignKey(Instrument)
创建一个立方体:
>>> c = Cube(['instrument__name', 'firstname'], Musician.objects.all(), len)
... #Cube(dimensions, queryset, aggregation_function)
... #You can use the Django field-lookup syntax for dates and foreign keys !!!
沿着一个(或多个)维度查询这个立方体:
>>> c.measure_dict('firstname', 'instrument__name', full=False) == {
... 'Miles': {
... 'trumpet': {'measure': 1},
... 'sax': {'measure': 0},
... 'piano': {'measure': 0},
... },
... 'John': {
... 'trumpet': {'measure': 0},
... 'sax': {'measure': 1},
... 'piano': {'measure': 4},
... },
... }
使用自定义的模板标签等等……