我有一个Django模型,我想在其中保存无模式的键值元数据,所以我使用的是django.contrib.postgres.fields.JSONField
。
键值数据是Pandas系列,默认情况下不是JSON可序列化的(由于numpy.int64,numpy.float64类型),所以我使用方便的series.to_json()
返回已经序列化的JSON字符串。
要将其保存到我的模型,我会在其上运行json.loads
。但是我知道当数据保存到Postgres时会调用json.dumps
。
如何避免这种不必要的反序列化/重新序列化步骤?
代码示例:
def create_model(pandas_series):
mdl = Model()
metadata = pandas_series.to_json() # gives a JSON string
mdl.metadata = json.loads(metadata) # string->dict, then dict->string
mdl.save()
答案 0 :(得分:4)
我以编程方式创建了一个包含千个元素的字典,它看起来像这样:
d = {...," a240":240," a243":243," a242",...}
然后我json.loads(json.dumps(d))
循环1000次。平均而言,1000次迭代需要510毫秒。
然后我创建了以下模型:
class JsonModel(models.Model):
jfield = JSONField()
将字典1000次插入数据库,如下所示:
JsonModel.objects.create(jfield = d)
此操作平均需要21秒。因此,真正的瓶颈似乎是将数据保存到数据库而不是序列化反序列化步骤。
总而言之,保存到数据库的速度比json转储/加载大约慢40倍(但是你的里程将根据字典的大小,数据库上的负载等而变化)。
基于上面的数字,不能转储/加载可能不值得。如果你热衷于尝试它,那么事情就是create a custom field。它可以像下面那样简单:
from django.contrib.postgres.fields import JSONField
class MyJsonField(JSONField):
def get_prep_value(self, value):
if isinstance(value, str):
return value
return super(MyJsonField,self).get_prep_value(value)
然后您的模型可以
class JsonModel(models.Model):
metadata = MyJsonField()
....
然后在创建db记录时,您可以传入json序列化sting而不是调用json.loads
mdl.metadata = metadata # no string->dict, then dict->string