ruby-on-rails - 可变列名的数据库设计

标签 ruby-on-rails ruby-on-rails-3

我遇到的情况涉及公司、项目和撰写项目报告的员工。

一家公司拥有许多项目、许多报告和许多员工。
一份报告由一名员工为公司的一个项目撰写。

各公司希望报告中包含不同的内容。假设一家公司想了解项目绩效和速度,而另一家公司想了解成本效益。有 5-15 个标准,每个公司都有不同的设置,所有这些标准都适用于该公司的所有项目报告。

我正在考虑不同的方法来做到这一点,但我目前的僵局是:

  • 在公司表中,添加文本字段criteria,其中包含按顺序排列的所需条件的数组。
  • 在报告表中,有一个 company_id 和列 criterion1criterion2 等。

我完全意识到这通常被认为是可怕的数据库设计 - 不优雅且不灵活。所以,我需要你的帮助!我怎样才能更好地构建它?


结论

出于以下原因,我决定在我的案例中使用序列化选项:

  1. 我对标准的要求很简单 - 每位员工提交报告后,无需搜索或排序。
  2. 我想最大限度地减少数据库负载 - 在要实现这些负载的地方,已经有一个大页面产生开销。
  3. 我希望避免使数据库结构复杂化,以满足我认为相对简单的需求。
  4. CouchDB 和 Mongo 目前不在我的保留范围内,因此我会将它们留到更需要的时候使用。

最佳答案

这将是使用 NoSQL 的绝佳机会!对我来说这似乎是教科书的用例。因此,请前往 CouchDBMongo并开始黑客攻击。

使用传统的数据库,您会稍微陷入数据标准化程度的问题:

  1. 一种“好”方式(意味着非常标准化)看起来像这样:

    class Company < AR::Base
      has_many :reports
      has_many :criteria
    end
    
    class Report < AR::Base
      belongs_to :company
      has_many :criteria_values
      has_many :criteria, :through => :criteria_values
    
    end
    
    class Criteria < AR::Base # should be Criterion but whatever
      belongs_to :company
      has_many :criteria_values
      # one attribute 'name' (or 'type' and you can mess with STI)
    end
    
    class CriteriaValues < AR::Base
      belongs_to :report
      belongs_to :criteria
      # one attribute 'value'
    end
    

    这使得 NoSQL 中的一些事情变得非常简单和快速,成为 SQL 中的三重或四重联接,并且您有许多几乎不执行任何操作的模型。

  2. 另一种方法是非规范化:

    class Company < AR::Base
      has_many :reports
      serialize :criteria
    end
    
    class Report < AR::Base
      belongs_to :company
      serialize :criteria_values
    
      def criteria
        self.company.criteria
      end
      # custom code here to validate that criteria_values correspond to criteria etc.
    end
    

    与此相关的是至少序列化标准(如果它们都是 bool 值,则可能是值)的相当聪明的方法是使用位字段。这基本上为您提供了或多或少的轻松迁移(难以删除和修改,但易于添加)和搜索能力,而无需任何开销。

    实现此功能的一个很好的插件是 Flag Shih Tzu我已经在几个项目中使用过并且可以推荐。

  3. 变量列(例如crit1crit2等)。

    我强烈建议不要这么做。您不会获得太多好处(它仍然不太容易搜索,因为您不知道您的信息在哪一列)并且会导致可维护性噩梦。想象一下,您的数据库有几百万条记录,突然有人需要 16 个条件。原本完全没有问题的事情突然间发生了一次迁移,向数百万条记录添加了一个完全无用的字段。

    另一个问题是,许多 ActiveRecord 魔法对此不起作用 - 您必须自己弄清楚 crit1 的含义 - 现在如果您不想添加验证这些字段会增加很多无意义的工作。

总结一下:看看 Mongo 或 CouchDB,如果这看起来不切实际,请继续保存您的东西 serialized 。如果您需要进行复杂的验证并且不太关心数据库负载,那么请进行标准化并采用选项 1。

关于ruby-on-rails - 可变列名的数据库设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5289099/

相关文章:

ruby-on-rails-3 - Rails form_for 提交按钮不起作用

ruby-on-rails-3 - 在开发中直接服务 Assets (无 Assets 管道)?

ruby-on-rails - Rspec - 测试方法的实例

ruby-on-rails - ActiveRecord group by on a join

javascript - 重定向到我的 Rails 应用程序的西类牙语或英语版本?

ruby-on-rails - rails : Is that possible to define named scope in a module?

ruby-on-rails-3 - Rails 3 : datetime_select with am/pm options

ruby-on-rails - 如何在 rails3 中创建动态路由和助手

ruby-on-rails - Rake 无法加载此类文件 cucumber

javascript - 使用 jQuery 单击选择单选按钮