我正在尝试使用mongodb作为后端在django中定义时间序列模型。我读到了一些best practices for timeseries data at the MongoDB Blog,我认为我理解得很清楚。但现在,我的问题是:如何使用django的模型语法定义这样的模型?我不确定这些是embedded documents
还是只是在模型字段中存储arrays
或dicts
。这是建议的mongo格式:
理想的mongo文档格式:
{
timestamp_hour: ISODate("2013-10-10T23:00:00.000Z"),
type: “memory_used”,
values: {
0: { 0: 999999, 1: 999999, …, 59: 1000000 },
1: { 0: 2000000, 1: 2000000, …, 59: 1000000 },
…,
58: { 0: 1600000, 1: 1200000, …, 59: 1100000 },
59: { 0: 1300000, 1: 1400000, …, 59: 1500000 }
}
}
一种解决方案是做这样的事情,一份文件包含一天的数据:
# models.py
class timeseries(models.Model):
date = models.DateField(null=True)
value_hour_0 = models.CharField(max_length='1024', blank=True)
value_hour_1 = models.CharField(max_length='1024', blank=True)
value_hour_...
value_hour_23 = models.CharField(max_length='1024', blank=True)
即使我将arrays
或dicts
存储在value_hour_n
字段中,它也不能提供查询文章中提到的文档的优势,例如{{ 1}}。有什么建议吗?
答案 0 :(得分:2)
我对结构是理想的格式不能不同意,我似乎总是把这种符号看作是对如何建模数组的“PHP理解”,但是这个不适合Mongo的解释。
由于我进一步详细介绍here的原因,我通常会发现以下结构更易于查询:
{
timestamp_hour: ISODate("2013-10-10T23:00:00.000Z"),
type: “memory_used”,
values: [
[ 999999, 999999, …, 1000000 ],
[ 2000000, 2000000, …, 1000000 ],
…,
[ 1600000, 1200000, …, 1100000 ],
[ 1300000, 1400000, …, 1500000 ]
]
}
这种方式(如在另一个答案中所解释的那样)你并不专门解决路径的任何部分来获取任何元素。子文档符号是单向,你必须完全指定每一个,不能做范围的东西或在不同的位置找到值。
使用数组无论如何都会获得免费的位置表示法,因此如果您想要或者在其中匹配,您可以values.59
甚至values.20.15
文档,数组中的 。
对于你的解决方案,你需要更多地使用它,但是这个和另一个阅读给出了一般的要点。
答案 1 :(得分:0)
你可以做你写的,但是如果你想每2小时或每30分钟存储一次值呢?所以这不是一个好习惯
怎么样:
class MyModelStat(models.Model):
#other fields like : nbr_views, nbr_clicks, rates ...
my_model = models.ForeignKey(MyModel, related_name="stats")
created_on = models.DateTimeField(auto_now_add=True)
previous = models.ForeignKey('self', blank=True, null=True, editable=False)
def save(self, **kwargs):
current_stats = self.my_model.current_stats
if current_stats is not None and self.id is None:
#iterate over the fields, and do your stuff
self.rates = current_stats.rates + 1
self.nbr_views = current_stats.nbr_views
#set the current stat as the previous for the new stat
self.previous = self.deal.current_stats
super(MyModelStat, self).save(**kwargs)
@receiver(post_save, sender=MyModelStat)
def set_mymodel_stats(sender, *args, **kwargs):
"""
Signal handler to ensure that a new stats is always chosen as the current stats - automatically. It simplifies stuff
greatly. Also stores previous revision for diff-purposes
"""
instance = kwargs['instance']
created = kwargs['created']
if created and instance.my_model:
instance.my_model.current_stats = instance
instance.my_model.save()