django - 我应该使用 JSONField 而不是 ForeignKey 来存储数据吗?
问题描述
我正面临两难境地,我正在创建一个新产品,我不想搞乱我在数据库中组织信息的方式。
我的模型有这两种选择,第一种是使用外键将它们链接在一起。
Class Page(models.Model):
data = JsonField()
Class Image(models.Model):
page = models.ForeignKey(Page)
data = JsonField()
Class Video(models.Model):
page = models.ForeignKey(Page)
data = JsonField()
etc...
第二个是将所有内容保存在Page
的 JSONField 中:
Class Page(models.Model):
data = JsonField() # videos and pictures, etc... are stored here
一个比另一个好,为什么?这对我将来组织数据库的方式有很大帮助。
我想也许第二个选项可能会更慢,因为每次发生变化时,所有的 json 都会被覆盖,但它会产生巨大的差异还是我说的是假的?
解决方案
AJSONField
混淆了底层数据,使得编写可读代码和充分使用 Django 的内置 ORM、验证和其他细节(ModelForm
例如 s)变得困难。虽然它可以灵活地将您想要的任何内容保存到数据库中(例如,在添加新字段时无需迁移数据库),但它消除了显式字段的清晰度并使得以后很容易引入错误。
例如,如果您开始在数据中保存一个新键,然后尝试在代码中访问该键,那么旧对象将没有它,并且您可能会发现您的应用程序崩溃,具体取决于您正在访问的对象。如果您使用单独的字段,则不会发生这种情况。
我总是尽量避免它,除非没有其他办法。
通常我在两种情况下使用 JSONField:
- 保存来自 3rd 方 API 的响应(例如作为审计跟踪)
- 保存对归档对象的引用(例如,当我的数据库中的实时产品发生变化但我仍然有引用该产品的订单时)。
如果您使用 PostgreSQL 作为关系数据库,它经过优化以在 JOIN 上具有超级性能,因此使用ForeignKey
s 实际上是一件好事。在您的代码中使用select_related
andprefetch_related
来优化查询的数量,但查询本身即使针对数百万个条目也可以很好地扩展。
推荐阅读
- c++ - 为什么此代码存在运行时错误?
- vim - 在vim中对十六进制颜色代码进行排序
- node.js - Route.post() 需要回调函数,但在使用 Passport 身份验证时得到了 [object Undefined]
- laravel - Laravel 6:批量插入与批量插入关系
- javascript - 刷新使用户在 react、redux、nodejs 和基于 cookie 的身份验证中注销
- java - 有人可以向我解释这个方法签名吗
- java - 如何将字符串类型的算术表达式转换为整数?
- php - 在 mariadb 中, Count(*) AS 某些东西不起作用。有没有更好的表达方式?
- javascript - 添加后台脚本时,Chrome 扩展弹出页面停止更新
- node.js - 成功的查询响应不会显示在 Postman 中..?