我们有一个包含大约5个核心实体的php / mysql系统。我们现在需要为客户添加基于每个项目为某些实体创建自定义字段的功能。
它们将包含标签,键,类型,默认值和可能允许的值。
这样他们就可以在UI中添加自定义日期字段或自定义下拉列表,并针对特定实体保存此值。
在mySQL数据库中存储此类数据的最佳方法是什么?我需要存储字段的配置,然后存储特定实体的当前值。
我在这里看了各种各样的选项.. https://ayende.com/blog/3498/multi-tenancy-extensible-data-model
但这不是真正的租赁级别,更像是项目级别。
我在想......
然后,我们在检索实体时创建实体与这些自定义值之间的关系。
问题在于,Values表中的行与自定义字段一样多 - 因此保存实体将导致X个额外行。最重要的是,这些都是版本化的,因此一旦创建了新版本,就会为该新版本创建另外的X行。
此外,你不能索引名称上的字段,连接会变得非常复杂我认为你必须加入配置和值来构建键值对以返回实体,你会如何选择基于自定义字段名称,当字段名称实际上是值?
我不想在表中添加动态列,因为这会影响整个系统中的所有entites - 而不仅仅是当前客户端/项目中的那些。
另一个选项是将值存储在JSON列中。
这可以在实体行本身customFields
或类似的。这将阻止每个字段的额外行,但也存在缺少索引等问题,并且仍然需要加入配置表。但是,如果key=value
存储在JSON中,您可以按属性名称执行查询... WHERE entity.customFields->"$.myCustomFieldName" > 1
。
将文件名存储在json中意味着一旦创建就无法更改它,而不会有太多痛苦。
如果有人对此方法有任何建议,或者引用我的文章会非常感激 - 我确信这已经解决了很多次......
答案 0 :(得分:0)
JSON记录:不!千万不!如果你这样做,只要等到某人实际使用你的系统几千万条记录,然后要求你搜索一个额外的字段。你的支持人员会诅咒你的名字。
键值存储。可能是。这个设计有一个非常广泛部署的存在证据:WordPress。它有一个名为wp_postmeta的表,包含应用于wp_posts(博客页面和帖子)的元数据字段。它被证明是成功的。
你需要做一些多次加入来使用这些东西。例如,要搜索高度和眼睛颜色,您需要
SELECT p.person_id, p.first, p.last, h.value height, e.value eye_color
FROM person p
LEFT JOIN attrib h ON p.person_id = h.person_id AND h.key='eye_color'
LEFT JOIN attrib e ON p.person_id = e.person_id AND e.key='height'
WHERE e.value='green' and CAST(h.value AS INT) < 160
正如WHERE
子句中的CAST所示,您也会遇到一些与数据类型相关的问题。
在这种属性查找中你需要LEFT JOIN操作;普通的内部JOIN操作将禁止具有缺少属性的行,这可能不适合您。
但是,如果你在索引方面做得很好,你就能从这种方法中获得不错的表现。
我的示例中设想的表结构没有您的表描述每个附加字段,但您知道如何添加它。它也没有明确支持多项目/多租户数据分离。但你也可以添加它。