【问题标题】:Dynamic table columns based on user preferences基于用户偏好的动态表列
【发布时间】:2013-06-18 06:38:44
【问题描述】:

场景

假设用户是推销员。 User 模型有许多 log_entries 用作销售数据的日常日志。用户还具有允许他们选择在其 log_entry 表单中可见的字段的首选项。所以,如果他们选择菠萝、香蕉和葡萄……这些就是表格中的字段。如果这些选择发生变化,数据不会丢失……只是在表单中不可见。 现在,假设用户刚刚选择了蔓越莓销售账户,但蔓越莓在他们的用户偏好表单中不是一个可选择的属性。他们需要能够创建那个“类别”。现在,菠萝季节结束了,所以他们登录到偏好设置并取消选中菠萝框并选中草莓框。现在,当他们在日志中输入数据时,将有一个草莓数据字段,但不是菠​​萝。菠萝数据没有消失……只是没有显示出来。

这种情况会带来一些挑战。一个是作为开发人员我不提前知道数据库列名称,因为用户可以动态创建新的“类别”(我可以要求用户联系我以根据需要添加更多,但是......)。而且,当用户创建一个新类别时...... log_entries 表不会有一个列来表示该新数据。

如何管理动态数据库列? postgres hstore 可以处理这个吗?

一行是基于日期的属于用户的条目。每列都包含特定于某个属性的数据(例如...一列可以标题为“草莓”,它将包含当天售出的单位数量)

【问题讨论】:

  • hstore 似乎是要走的路。但是,如果一个用户创建了一个类别,那么我希望该类别可供所有用户使用。 hstore 似乎是特定于用户的,可能不是很有条理
  • 我能想到的最佳选择是为我能想到的用户可能需要登录的每种数据类型创建一个列...然后让他们提交请求让我添加更多数据列(如果需要)。
  • 我刚刚想到的另一个选项是在数据库中创建一组自定义列,例如...custom_one、custom_two 等(可能有 10 个)。然后,创建一个包含两个字段的 Usercustom 模型...custom_col_ref:string 和 custom_col_label:string。 custom_col_ref 将存储存储数据的实际列名,而 custom_col_label 将存储要在表单中使用的标签。然后,使用 if 语句在表单中显示/隐藏该字段..."if Usercustom.find_by_custom_col_ref("custom_one").exists?"... 在表单中显示该列的字段。

标签: ruby-on-rails-3 postgresql


【解决方案1】:

通常的方法是:

  • EAV
  • hstore
  • XML
  • JSON

见:

整个“使列对其他用户可用”的事情只要求您保留一个“自定义键”表,您可以在用户定义以前未使用的键时添加该表。

使用动态 DDL 添加列一开始听起来很合理,但是您可以存储多少列以及一行可以有多“宽”是有限制的。当您添加更多列时,扫描表的性能会变得更差,尽管大部分为空的“稀疏”列相对便宜。添加列需要排他锁,这在繁忙的系统上可能需要一些时间,但如果未将其定义为NOT NULL DEFAULT ...,则添加列本身会非常快。一开始它会很好用,但我怀疑你以后会后悔的。

【讨论】:

  • “使用动态 DDL 添加列一开始听起来很合理”,然后你必须说服 ORM 来处理这类事情。在一桶鱼钩中钓苹果可能会更好。
  • @muistooshort 啊,是的,ORM。娱乐时间。令人愉快的类比。
  • 谢谢,克雷格。所以,如果我知道用户需要的 90% 的字段是否适合将这些列添加到数据库中......即使对于一些/许多用户来说,这些列中的许多列总是为空的?我正在使用 postgres,所以我可以使用 hstore……但是,我仍在想办法在我的视野中做到这一点。
  • @hellion 如果您不是在谈论数百个字段,并且您不打算动态添加和删除它们,那么它可能没问题。我敢肯定,随着用户的要求越来越高,您会后悔的;我会从一开始就让它充满活力。至少我会使用我加入的边表,而不是将列添加到主表中,这样我以后可以改变我的方法而不会那么痛苦。
【解决方案2】:

我最终没有使用 hstore,因为我认为它不是最好的解决方案。可能是……我只是不想花时间去摸索。我最终做的是改变我现有的 Preferences 模型并创建一些新模型。在 Preferences 模型中,我有一个字符串列,其中存储了引用模型的名称和模型项 id...然后在需要时将字符串常量化。

所以,如果用户想要在他们的偏好中加入水果,他们可以点击“添加更多水果”,如果他们想要的特定水果没有列出,他们可以添加它。当他们保存他们的偏好时,选择的水果 id 将被存储为一个整数,并通过一个隐藏字段引用的模型(在本例中为“水果”)将被存储为一个字符串。

然后,在用户偏好索引页面中,我有一个标题为水果的部分(如果用户有任何水果偏好)。该查询只是在 Preference 表中搜索与 current_user 匹配的用户、与“Fruit”匹配的 modelref,并使用未关联的存储 id 查找水果记录。

我可能没有很好地解释这一点......但是,也许它会帮助其他想要做类似事情的人。

【讨论】:

  • 我确实最终使用了 hstore。绝对是要走的路。
猜你喜欢
  • 2018-09-20
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-01
  • 2019-02-20
  • 2020-08-16
  • 1970-01-01
相关资源
最近更新 更多