属性表模式与将所有属性存储在 json 列中 [重复]

Posted

技术标签:

【中文标题】属性表模式与将所有属性存储在 json 列中 [重复]【英文标题】:properties table pattern vs storing all properties in json column [duplicate] 【发布时间】:2019-09-15 04:11:10 【问题描述】:

我想要一些关于让模型可以在属性表中通过关系(使用 laravel 关系)访问的所有属性与将所有属性/设置存储在同一个表中但在 json 列中的一些反馈。

目前,我的应用程序有一个名为 settings 的属性表,它本质上也是多态的,因此多个模型可以在那里存储它们的属性。该表有类似的列

key (string), 
value(string), 
type (string) - tells if the value is of string, integer, boolean, json type 

这样我就不会向 javascript 前端发送字符串,而是可以发送字符串、整数、布尔本机类型,以便更好地处理前端中的类型。在使用 php 函数将字符串值转换为 int、boolean、json 或字符串之前,我会在将属性发送到前端之前进行此转换,具体取决于类型。

这意味着如果一个模型有 40 个属性,所有属性都存储在自己的行中,因此创建一个模型会导致创建 40 行来存储它可能具有的所有属性。

现在上述方法与我只有一个 json 列的方法相比,我们可以将其称为设置,然后我将所有这 40 个属性转储到那里。

使用 json 列方法可以赢得什么?我刮掉了一张桌子,刮掉了一个额外的关系,每次我做一些查询时都需要在这个模型上加载。每次获取属性时,我也不必将它们转换为整数、布尔值、json 或字符串。 (记住上面的类型列)要记住这些属性不需要是可搜索的,我只需要它们来读取它们。我永远不会在查询中使用它们来返回基于这些属性的帖子。

使用哪个更好,我正在构建一个 CMS,顺便说一句,您可以在此处看到它的实际效果: https://www.youtube.com/watch?v=pCjZpwH88Z0

【问题讨论】:

EAV 很烂;避免它。 @RickJames 为什么它很烂?你有什么建议用 json 代替? niko - mysql.rjweb.org/doc.php/eav 【参考方案1】:

只要您不尝试使用属性进行搜索或排序,就没有太大区别。

如您所说,在模型表中放置一个 JSON 列可以避免与属性表连接。

我认为您的属性表实际上需要多一列来命名属性。所以应该是:

key (string), 
property (string),
value(string), 
type (string) - tells if the value is of string, integer, boolean, json type 

两种解决方案的缺点非常相似。

与查询普通列相比,使用任一解决方案的查询都将更加复杂。

将非字符串值存储为字符串效率低下。将数字或日期时间值存储为字符串比存储本机数据类型需要更多空间。

您不能对属性应用约束。没有办法强制属性(您将使用 NOT NULL 作为普通列)。无法强制执行唯一性或外键引用。

我能想到的一种情况是 JSON 具有优势。如果您的某个自定义属性本身是多值的,则有一种在 JSON 中表示它的简单方法:作为 JSON 文档中的一个数组。但是如果你尝试使用一个属性表,你会为一个属性存储多行吗?或者将一组值序列化为一行的数组?两种解决方案都感觉很笨拙。

因为“无模式属性”模式无论如何都打破了关系数据库设计的规则,所以您无能为力“做对”。您选择了两害相权取其轻,因此您可以随意使用使您的代码更方便的解决方案。

【讨论】:

btw "key" 命名属性。如果您将“key”误认为被用作“id”,那里还有“id”列 :) 当涉及到属性表时,1 个属性 = 1 行,例如,我将这些值保存在一行中:key : "showSomeSetting", value: true, type: boolean 这里的问题是,如果我有 40 个属性,我可以很容易地得到 40 行,并且每个属性值列都可以是“string”、“integer”、“ json”或“boolean”,一旦我从 db 获得关系,我必须手动将它们转换为那些 >与查询普通列相比,任何一种解决方案的查询都将更加复杂。 >将非字符串值存储为字符串效率低下。将数字或日期时间值存储为字符串比存储本机数据类型需要更多空间。 >您不能对属性应用约束。没有办法强制属性 >如果您的自定义属性之一本身是多值的> 我有一个类型,我将它保存为 json 类型在 1 行中。在检索关系并再次检查所有属性以查看它们是什么类型后,我必须手动将其转换回 json。这里没有问题我有工作代码并且速度很快。但这并不像我只使用一个 json 列那样优雅,那么我不必遍历所有属性检查类型并将它们正确地转换为正确的类型。

以上是关于属性表模式与将所有属性存储在 json 列中 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MySQL 中的 JSON 数组内的元素中提取特定属性的所有值?

重命名 TableRow 属性名称

实体框架 6:将子对象添加到父列表与将子对象的导航属性设置为父对象

修改存储在 Table Column 中的 JSON 字符串的属性值

OOP:将对象与将属性传递给方法

js对象在sqlite中保存和读取