替换 EAV 时 JSON(B) 中的数据完整性
Posted
技术标签:
【中文标题】替换 EAV 时 JSON(B) 中的数据完整性【英文标题】:Data integrity in JSON(B) when replacing EAV 【发布时间】:2020-02-03 05:34:44 【问题描述】:我正在为一个新应用程序实现一个数据库,我正在考虑使用JSON
字段而不是传统的EAV
方法。一切似乎都还好,但有一个大问题我不知道如何解决。
例如;在传统的EAV
模型中,我们将有三个表格;
第三张表中的标识符始终是其他两个表之一的主键,而不是值本身。如果我更改属性的名称,它的主键保持不变,因此不会影响 第三张表中的数据完整性。
现在输入JSON
。据我了解,用JSON
替换EAV
的全部意义在于将所有值存储在字段本身中。所以我们的记录可能是这样的。
"color": "Blue",
"size": "Large"
而不是通过主键存储值。
所以我的问题是,如果我在路上,将颜色的标题从Blue
更改为Purple
,我该如何处理数据完整性?因为在经典的EAV
模型中主键不会改变。
我正在使用Postgresql
数据库和Django
。
【问题讨论】:
【参考方案1】:使用 Django ORM,操作 JSON 字段值的唯一方法是 迭代模型。但您可以查询/过滤个别字段:
假设你有这个模型:
from django.contrib.postgres.fields import JSONField
from django.db import models
class Thing(models.Model):
attributes = JSONField()
你应该可以查询蓝色的东西(见Querying JSONField):
blue_things = Thing.objects.filter(attributes__color='Blue')
现在您可以遍历这些模型实例并更新值:
for thing in blue_things:
thing.attributes['color'] = 'Purple'
thing.save()
您可能希望在事务中执行此操作。
PostgreSQL 允许您直接操作 JSONB 字段:
UPDATE appname_thing SET attributes = attributes || '"color": "Purple"' WHERE attributes->>'color' = 'Blue';
据我所知,Django 目前不支持此功能,因此您必须perform a raw query。
【讨论】:
【参考方案2】:我个人不熟悉 Django,但如果您想利用 PostgreSQL 的 JSON 功能,我可能会依赖与您更随意的 JSON 分开的主键列。比如:
CREATE TABLE stuff (
id SERIAL NOT NULL PRIMARY KEY,
data JSON NOT NULL
);
这样您就可以将您的id
列作为可靠的参考,并且可以对 JSON 进行任何您喜欢的操作。如果您对 JSON 有一个已知/可预测的结构,您可以create indices 在查询 到 JSON 数据时帮助提高性能。
原答案:
我不清楚您将使用哪种数据库产品,但熟悉 MongoDB,一个面向 JSON 文档的数据库,我可以告诉您它是如何工作的。当您插入一个文档时,如果您不提供它,则会添加一个 _id
字段,MongoDB 称之为 ObjectId
。所以,如果你插入你的示例 JSON,你会得到类似的东西:
"_id": ObjectId("5d97d46a54198e0797d86457"),
"color": "Blue",
"size": "Large"
如果您只想更新该文档,可以在“where 子句”中使用 _id
,例如:
db.collection.updateOne(
_id: ObjectId("5d97d46a54198e0797d86457")
,
$set:
color: "Red",
size: "Medium"
);
同样,不知道您使用的是什么数据库,这可能是离谱的。如果你在 PostgreSQL 之类的东西中处理 JSONB,那么你通常会包含一个 serial
或类似的列来维护一个固定的主保留,就像你提到的那样。
【讨论】:
我已经编辑了原始问题,感谢您的回答。以上是关于替换 EAV 时 JSON(B) 中的数据完整性的主要内容,如果未能解决你的问题,请参考以下文章
在保持 JSON 文件完整的同时替换 Javascript 中的字符串